Forum: PC-Programmierung C uint16_t zu char[] ohne malloc


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Bartosz B. (bartosz)


Lesenswert?

Hallo,
ich habe diesen Code gefunden, der einen uint16_t zu einem Char-Array 
macht. Der Vorteil ist, dass man nicht itoa benutzen muss.
Der Nachteil ist, dass free(str) nie ausgeführt wird.
Daher würde ich mich freuen, wenn ihr Verbesserungsvorschläge habt.
1
const char* uint16_t_to_String(uint16_t number)
2
{
3
  int length = snprintf(NULL, 0, "%d", number);
4
  char* str = (char*) malloc(static_cast<size_t>(length) + 1);
5
  snprintf(str, static_cast<size_t>(length + 1), "%d", number);
6
  return str;
7
  free(str); //Problem -> never executed
8
}

Der Aufruf:
1
char Number_as_String[6]{};
2
      const char* Pointer_to_the_NumberString = uint16_t_to_String(cnt);
3
      for (long long k = 0; k < 6ll; k++)
4
      {
5
        Number_as_String[k] = *(Pointer_pointing_to_the_NumberString + k);
6
        if (k > 0ll && Number_as_String[k] == '\0') //  If there is space left, there is no need to overwrite it with nonsense.
7
        {
8
          break;
9
        }
10
      }
mit cnt als uint16_t

Viele Grüße
Bartosz

: Bearbeitet durch User
von A. S. (achs)


Lesenswert?

Bartosz B. schrieb:
> Der Vorteil ist, dass man nicht itoa benutzen muss.

Warum dann nicht sprintf?

> Der Nachteil ist, dass free(str) nie ausgeführt wird.

Das kann nur der Aufrufer, der weiß, wann fertig.

Was soll der Code denn machen?

von Rolf M. (rmagnus)


Lesenswert?

Das ist kein C, sondern C++, denn static_cast gibt es nur dort.

Bartosz B. schrieb:
> Der Vorteil ist, dass man nicht itoa benutzen muss.

Warum ist das ein Vorteil, außer weil das keine Standardfunktion ist?

> Der Nachteil ist, dass free(str) nie ausgeführt wird.

Der Aufrufer muss es halt manuell ausführen. Nur der weiß ja, wann er 
den Speicher nicht mehr braucht. Es gibt in C zwei gängige Methoden:
- die Funktion holt sich den Speicher dynamisch und übergibt dem 
Aufrufer die Pflicht, den wieder freizugeben
- der Aufrufer stellt der Funktion bei Aufruf Speicher zur Verfügung und 
die Funktion schreibt einfach nur dort hinein

> int length = snprintf(NULL, 0, "%d", number);

Der Format-String für int16_t wäre streng genommen
1
"%" PRIi16

Und warum snprintf statt sprintf?

> for (long long k = 0; k < 6ll; k++)

Warum long long für einen Schleifenzähler, wenn der nur bis 6 zählt?

>       {
>         Number_as_String[k] = *(Pointer_pointing_to_the_NumberString +
> k);

Warum auf der einen Seite den []-Operator und auf der anderen Seite die 
umständliche Schreibweise für das selbe?

>         if (k > 0ll && Number_as_String[k] == '\0') //  If there is
> space left, there is no need to overwrite it with nonsense.
>         {
>           break;
>         }

Macht diese ganze Schleife hier nicht im Prinzip das gleiche wie ein 
ordinäres
1
strcpy(Number_as_String, Pointer_pointing_to_the_NumberString);
?

von Bartosz B. (bartosz)


Lesenswert?

Guten Morgen, Rolf!
Rolf M. schrieb:
> Das ist kein C, sondern C++, denn static_cast gibt es nur dort.
Ja, also ja, grundsätzlich ist mein Code in C geschrieben. Ich arbeite 
derzeit mit Visual Studio 2019 CE und habe ein C++ Projekt aufgemacht. 
Daher kam seitens Visual Studio der Vorschlag, static_cast zu verwenden.

> Bartosz B. schrieb:
>> Der Vorteil ist, dass man nicht itoa benutzen muss.
>
> Warum ist das ein Vorteil, außer weil das keine Standardfunktion ist?
Genau deswegen, so habe ich das gelernt. Sagst du mir nun, ich darf 
freien Gewissens itoa verwenden?

>> Der Nachteil ist, dass free(str) nie ausgeführt wird.
>
> Der Aufrufer muss es halt manuell ausführen. Nur der weiß ja, wann er
> den Speicher nicht mehr braucht. Es gibt in C zwei gängige Methoden:
> - die Funktion holt sich den Speicher dynamisch und übergibt dem
> Aufrufer die Pflicht, den wieder freizugeben
> - der Aufrufer stellt der Funktion bei Aufruf Speicher zur Verfügung und
> die Funktion schreibt einfach nur dort hinein

Ok, dann werde ich das einbauen. Kannst du mir bitte einen Vorschlag 
geben? Aus dem Kopf würde ich sagen: str global definieren und dann 
später in der main freigeben.

>> int length = snprintf(NULL, 0, "%d", number);
>
> Der Format-String für int16_t wäre streng genommen
>
1
> "%" PRIi16
2
>
Verdammt, normalerweise achte ich auf so etwas sehr genau ...

> Und warum snprintf statt sprintf?
Kannte ich so noch nicht. C / C++ ist bei mir sehr lange her, ich habe 
gerade wieder Lust drauf.

>> for (long long k = 0; k < 6ll; k++)
>
> Warum long long für einen Schleifenzähler, wenn der nur bis 6 zählt?
Weil es eine 64-bit-Adresse ist (ich debugge unter x64) und ich daher 
richtig inkrementieren will.
>
>>       {
>>         Number_as_String[k] = *(Pointer_pointing_to_the_NumberString +
>> k);
>
> Warum auf der einen Seite den []-Operator und auf der anderen Seite die
> umständliche Schreibweise für das selbe?
>
1
>>         if (k > 0ll && Number_as_String[k] == '\0') //  If there is
2
>> space left, there is no need to overwrite it with nonsense.
3
>>         {
4
>>           break;
5
>>         }
6
>
> Macht diese ganze Schleife hier nicht im Prinzip das gleiche wie ein
> ordinäres
>
1
> strcpy(Number_as_String, Pointer_pointing_to_the_NumberString);
2
>
> ?
Danke danke! Habe es geändert und es funktioniert.
Wie gesagt, in C bin ich nicht so fit.

*Edit:*
habs nun so gemacht
1
const char* uint16_t_to_String(uint16_t number)
2
{
3
  static char buffer[6]{};
4
  sprintf(buffer, "%d", number);
5
  return buffer;
6
}
Ich musste das Keyword static miteinbauen, da sonst die Warnung kam, 
dass der Rückgabewert ungültig sein könnte.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Bartosz B. schrieb:
> habs nun so gemacht

Warum eine extra Funktion für 1 (wenn du buffer nicht brauchst) oder 2 
Zeilen?

> Ich musste das Keyword static miteinbauen,

Das macht aber andere Probleme.

von A. S. (achs)


Lesenswert?

Bartosz B. schrieb:
> Hallo,
> ich habe diesen Code gefunden, der einen uint16_t zu einem Char-Array
> macht.

Bartosz B. schrieb:
> grundsätzlich ist mein Code

Hast Du den Code nun gefunden (wo?) oder selber geschrieben?

Falls selbst, was soll der eigentlich tun. Falls Hausaufgabee, poste die 
Aufgabe.

Der Code kommt zwar ohne itoa aus, macht aber auch etwas völlig anderes.


Falls Du nur itoa ersetzen willst, zeige den originalen Code mit itoa.

von Imonbln (Gast)


Lesenswert?

Bartosz B. schrieb:
> Ich musste das Keyword static miteinbauen, da sonst die Warnung kam,
> dass der Rückgabewert ungültig sein könnte.

Vorsicht, das Keyword Static hat in C zwei Bedeutungen abhängig davon, 
wo es steht. In deinen Fall bedeutet es, das der Speicher Bereich 
Buffer, genau einmal existiert und bei jeden Aufruf der Funktion 
derselbe Bereich mit der aktuellen Zahl beschrieben wird. Solltest du 
also so was machen.
1
a = uint16_t_to_String(15);
2
b = uint16_t_to_String(4);
3
4
if (a == b) 
5
  printf("a gleich b \n");

Wirst du dich Wundern, das a und b gleich sind. Da sie auf den gleichen 
Speicher zeigen.

von Dirk B. (dirkb2)


Lesenswert?

Imonbln schrieb:
> Wirst du dich Wundern, das a und b gleich sind. Da sie auf den gleichen
> Speicher zeigen.

Demnach gibt auch ein strcmp Gleichheit.

von 900ss D. (900ss)


Lesenswert?

Bartosz B. schrieb:
>>> for (long long k = 0; k < 6ll; k++)
>>
>> Warum long long für einen Schleifenzähler, wenn der nur bis 6 zählt?
>
> Weil es eine 64-bit-Adresse ist (ich debugge unter x64) und ich daher
> richtig inkrementieren will.

Ich glaube, du brauchst noch (wieder?) Grundlagen. Überlege nochmal, was 
dein Zähler macht (Wertebereich und notwendige Anzahl Bits) und ob es 
tatsächlich eine Adresse ist.
Weshalb würde denn falsch inkrementiert, wenn du nur uint8_t nutzen 
würdest?

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Bartosz B. schrieb:
> Guten Morgen, Rolf!
> Rolf M. schrieb:
>> Das ist kein C, sondern C++, denn static_cast gibt es nur dort.
> Ja, also ja, grundsätzlich ist mein Code in C geschrieben. Ich arbeite
> derzeit mit Visual Studio 2019 CE und habe ein C++ Projekt aufgemacht.
> Daher kam seitens Visual Studio der Vorschlag, static_cast zu verwenden.

In C++ sollte man auch den static_cast bevorzugen, aber der C-Stil-Cast 
geht genauso. Deine Nutzung ist aber nicht so ganz konsistent:

Bartosz B. schrieb:
> char* str = (char*) malloc(static_cast<size_t>(length) + 1);

Links vom malloc benutzt du einen C-Cast, rechts einen static_cast. In C 
wird übrigens emfohlen, den ersten Cast wegzulassen. In C++ ist er aber 
notwendig.

>> Bartosz B. schrieb:
>>> Der Vorteil ist, dass man nicht itoa benutzen muss.
>>
>> Warum ist das ein Vorteil, außer weil das keine Standardfunktion ist?
> Genau deswegen, so habe ich das gelernt. Sagst du mir nun, ich darf
> freien Gewissens itoa verwenden?

Es gibt viele Funktionen, die nicht Standard sind. Wenn du itoa 
verwendest, wird natürlich die Portabilität des Code eingeschränkt. Das 
heißt aber nicht, dass man sie auf gar keinen Fall nutzen sollte.

> Ok, dann werde ich das einbauen. Kannst du mir bitte einen Vorschlag
> geben? Aus dem Kopf würde ich sagen: str global definieren und dann
> später in der main freigeben.

Wie du den string definieren musst, hängt davon ab, wo er nachher 
verwendet werden soll.

>>> for (long long k = 0; k < 6ll; k++)
>>
>> Warum long long für einen Schleifenzähler, wenn der nur bis 6 zählt?
> Weil es eine 64-bit-Adresse ist (ich debugge unter x64) und ich daher
> richtig inkrementieren will.

Wie breit die Adressen sind, kann dir an der Stelle egal sein. Wenn du 
einen allgemeinen Typ für so etwas willst, der sich aber an die 
jeweilige Plattform anpasst, kannst du z.B. size_t nehmen. Aber 
funktionieren würde hier prinzipiell jeder beliebige Integer-Typ.

> *Edit:*
> habs nun so gemacht
> const char* uint16_t_to_String(uint16_t number)
> {
>   static char buffer[6]{};
>   sprintf(buffer, "%d", number);
>   return buffer;
> }
> Ich musste das Keyword static miteinbauen, da sonst die Warnung kam,
> dass der Rückgabewert ungültig sein könnte.

Kann man machen, aber dann musst du bedenken, dass der String bei jedem 
Aufruf der Funktion überschrieben wird und dass sie nicht reentrant ist. 
Das heißt, es wird zu Problemen kommen, wenn du die Funktion aus 
mehreren Threads gleichzeitig aufrufst.
Was ich als zweite Variante genannt hatte, war, dass dein 
uint16_t_to_String einen weiteren Parameter bekommt, der ein Zeiger auf 
den Speicherbereich ist, wo die Funktion ihr Ergebnis hinschreiben soll. 
Dann kannst du dir auch die anschließende Kopieraktion sparen, weil du 
es gleich in den Zielstring schreiben kannst.

von Gerald K. (geku)


Lesenswert?

A. S. schrieb:
> Das kann nur der Aufrufer, der weiß, wann fertig.

Oder der Empfänger, der diese Information bearbeitet und auswertet.

Wird free() in der oder von der Quelle aufgerufen, dann würde dem 
Empfänger die Information nicht mehr zur Verfügung stehen und auf einen 
ungültigen Zeiger zugreifen.

Es kann nicht schaden mit free() den Zeiger auf NULL zu setzen. Damit 
kann später die Gültigkeit überprüft werden.

von Dirk B. (dirkb2)


Lesenswert?

Gerald K. schrieb:
> Es kann nicht schaden mit free() den Zeiger auf NULL zu setzen. Damit
> kann später die Gültigkeit überprüft werden.

Dann ist aber ein Fehler im Programm.

von Bartosz B. (bartosz)


Lesenswert?

Hallo zusammen,

ersteinmal möchte ich mich für die Antworten bedanken.
Er ist keine Hausaufgabe, ich bin nicht mehr an der Uni. Ich 
programmiere nur privat 🙂

Dieser Code hier
1
const char* uint16_t_to_String(uint16_t number)
2
{
3
4
  int length = snprintf(NULL, 0, "%d", number);
5
  char* str = (char*) malloc(static_cast<size_t>(length) + 1);
6
  snprintf(str, static_cast<size_t>(length + 1), "%d", number);
7
  return str;
8
  free(str); //Problem -> never executed
9
}

kommt von Stackoverflow, allerdings habe ich die Seite nicht mehr im 
Browserverlauf. Ist zu lange her, da ich nur am Wochenende programmiere 
und es länger her ist. Jedenfalls habe ich nach "C Int to String" 
gegoogelt. Der restliche Code in meinem Programm kommt einzig und allein 
von mir.
Und auf Stackoverflow habe ich auch gelesen, dass itoa nicht mehr 
Standard wäre. Aber Stackoverflow weiß auch nicht alles. Das 
**static_cast<size_t>** hat Visual Studio mir vorgeschlagen. Und das 
Problem, dass free(str) nicht ausgeführt wird, habe ich mit einem 
Analysetool bemerkt.
Um es kurz zu machen: Ich werde nun itoa verwenden, da  Imonbln und ihr 
alle eigentlich mich auf das Problem mit dem Keyword static aufmerksam 
geamcht habt. Ich habe heute früh noch beim Debuggen gesehen, dass der 
Speicherbereich immer gleich ist, habe aber nicht die Gefahr gesehen – 
danke für den Hinweis!

Die Schleife
1
for (long long k = 0; k < 6ll; k++)
 ist nun raus. Muss man denn grundsätzlich kein long long hernehmen, um 
einen Pointer zu inkrementieren? Beispiel:
1
.... = *(Pointer_pointing_to_the_NumberString + k)
 erhöht ja erst die Adresse und holt davon den Wert. – Habe ich gedacht. 
Aber  Rolf M. hat das bereits beantwortet.

Danke auch an der Stelle für das schöne Wort réentrant 🙂


PS: Worum geht es hier eigentlich?
Ich möchte die C-Strings (also keine Strings sondern Char-Arrays) "A1", 
"A2", "B1" (samt den Anführungszeichen) kreieren und dazu mache ich nun 
sowas:
1
/*Zahl als String*/
2
3
      char Number_as_String[6]{};
4
      itoa(cnt, Number_as_String, 10);
5
6
      /*-------------------------------------------------------------------*/
7
      /* macht „"A1"“ etc draus */
8
9
      char Acell[5]{};
10
      strcat(Acell, "\x22"); // "
11
      strcat(Acell, "A");
12
      strcat(Acell, Number_as_String);
13
      strcat(Acell, "\x22"); // "
Das brauche ich, um eine xml-Datei einzulesen und die Values "A1" etc zu 
finden. Weil das Einbinden von DLLs über Nuget um eine Excel-Datei 
einzulesen nicht funktioniert hat.
In der Excel-Datei habe ich drei Spalten: in der linken stehen 
Datumsangaben, in der Mitte kann eine 1 oder nichts stehen, rechts 
steht immer eine 1 oder eine 0 (aber immer etwas).
1
01.01.2000     1     1
2
02.01.2000           1
3
03.01.2000           1
Das Ganze hatte natürlich Probleme zur Folge. Weil in der xml nun für 
"B1"
1
<v>1</v>
 stand und für "B2" nicht.
Das Einlesen der xml funktioniert aber bereits!! Ich wollte mich hier 
nur einmal bezüglich der Int-to-String-Geschichte melden. Ich habe 
allerdings keine Schwierigkeiten damit, euch den gesamten Code zu zeigen 
– wenn ihr Lust habt. Ist allerdings etwas mehr. 269 Zeilen. Und ich 
habe noch nicht die Werte zusammenhängend gespeichert. Das muss noch 
gemacht werden.

von foobar (Gast)


Lesenswert?

> Ich möchte die C-Strings "A1", "A2", "B1" (samt den Anführungszeichen)
> kreieren
1
   char cell[16];
2
   ...
3
   sprintf(cell, "\"%c%u\"", 'A', 10);

von Dirk B. (dirkb2)


Lesenswert?

Bartosz B. schrieb:
> kommt von Stackoverflow,

Das free steht in dem Code als Erinnerung, dass es gemacht werden muss.
Oder hättest du daran gedacht?

> Und auf Stackoverflow habe ich auch gelesen, dass itoa nicht mehr
> Standard wäre.

Das gehörte noch nie einem C-Standard an.
(wenn man C89 als ersten Standard annimmt, davor gab es viele Varianten)

Ist dir die Mächtigkeit von der printf-Familie überhaupt bewußt?
Deine ganz strcat-Orgie ist damit ein Einzeiler (siehe Beitrag von 
foobar)

Zudem ist dein Acell sehr knapp bemessen und die Magic Numbers \x22 
machen den Code auch nicht lesbarer.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Bartosz B. schrieb:
> Das Einlesen der xml funktioniert aber bereits!!

Das ist in C leider keine Garantie für richtigen Code
(So wie es aussieht, übersetzt du C mit einem C++ Compiler)

> Ich wollte mich hier
> nur einmal bezüglich der Int-to-String-Geschichte melden. Ich habe
> allerdings keine Schwierigkeiten damit, euch den gesamten Code zu zeigen
> – wenn ihr Lust habt. Ist allerdings etwas mehr. 269 Zeilen.

269 Zeilen ist Nichts.
Wenn du das machst - es gibt bestimmt Optimierungen und Fehler - dann 
aber als Anhang und nicht im Beitrag.

von Dirk B. (dirkb2)


Lesenswert?

Bartosz B. schrieb:
> itoa(cnt, Number_as_String, 10);
> …


foobar schrieb:
>> Ich möchte die C-Strings "A1", "A2", "B1" (samt den
> Anführungszeichen)
>> kreieren
> 1   char cell[16];
> 2   ...
> 3   sprintf(cell, "\"%c%u\"", 'A', 10);

Der letzte Parameter bei der oben gezeigten itoa-Variante ist die Basis, 
der erste der int-Wert. (es gibt auch itoa ohne Basis)

Dann ist das eher:

sprintf(cell, "\"%c%d\"", 'A', cnt);

Da cnt aber als uint16_t definiert ist (warum eigentlich), wäre es dann

sprintf(cell, "\"%c%"PRIi16“\"", 'A', cnt);

von Rolf M. (rmagnus)


Lesenswert?

Dirk B. schrieb:
> Da cnt aber als uint16_t definiert ist (warum eigentlich), wäre es dann
>
> sprintf(cell, "\"%c%"PRIi16“\"", 'A', cnt);

Das wird allerdings nicht funktionieren, wenn er das als C++(>=11) 
compiliert, da dort "%c%"PRIi16 als benutzerdefiniertes string-literal 
interpretiert wird. Man braucht ein zusätzliches Leerzeichen:
1
sprintf(cell, "\"%c%" PRIi16"\"", 'A', cnt);

Hier ist auch das Anführungszeichen nach dem PRIi16 gefixt. ;-)

von Bartosz B. (bartosz)


Lesenswert?

Dirk B. schrieb:
> Bartosz B. schrieb:
>> kommt von Stackoverflow,
>
> Das free steht in dem Code als Erinnerung, dass es gemacht werden muss.
> Oder hättest du daran gedacht?
Achso...nein.

> Ist dir die Mächtigkeit von der printf-Familie überhaupt bewußt?
Nein.
> Deine ganz strcat-Orgie ist damit ein Einzeiler (siehe Beitrag von
> foobar)
Danke dafür.

Ich werde die .cpp-Datei hier hochladen, wenn ich wieder Zeit habe. Ich 
muss gleich los zur Arbeit.

> Da cnt aber als uint16_t definiert ist (warum eigentlich)

Weil ich dachte, dass das reicht. Ich werd niemals über 65535 Zeilen in 
meiner Excel-Datei haben.

: Bearbeitet durch User
von Kaj (Gast)


Lesenswert?

Bartosz B. schrieb:
> Ich werd niemals über 65535 Zeilen in
> meiner Excel-Datei haben.
Und wir werden niemals mehr als 640kB RAM brauchen... ;)

Gerald K. schrieb:
> Es kann nicht schaden mit free() den Zeiger auf NULL zu setzen.
free/delete setzt den Pointer nicht auf NULL, das muss man von Hand 
machen. free/delete gibt nur den Speicher frei.


Bartosz B. schrieb:
> Ich musste das Keyword static miteinbauen, da sonst die Warnung kam,
> dass der Rückgabewert ungültig sein könnte.
Natuerlich.
1
int foo(void)
2
{
3
    int local_var = 0;
4
5
    return local_var; //  es wird der WERT zurueck gegeben
6
}
7
8
int* bar(void)
9
{
10
    int local_var[6] = {0};
11
12
    return local_var; // local_var ist ein Array, es wird nur die STARTADRESSE
13
                      // des Arrays zurueck gegeben. Nach verlassen der
14
                      // Funktion ist die Adresse/die Daten an dieser Adresse
15
                      // nicht mehr gueltig.
16
}
17
18
19
int* foobar(void)
20
{
21
    static int local_var[6] = {0};
22
23
    return local_var; // local_var ist ein Array, es wird nur die STARTADRESSE
24
                      // des Arrays zurueck gegeben. Wegen static liegt 
25
                      // local_var nicht im Stack der Funktion foobar, und ist 
26
                      // deswegen auch nach verlassen der Funktion gueltig.
27
}

von = {0}; (Gast)


Lesenswert?

Bartosz B. schrieb:
> char Acell[5]{};
>       strcat(Acell, "\x22"); // "
>       strcat(Acell, "A");
>       strcat(Acell, Number_as_String);
>       strcat(Acell, "\x22"); // "

Acell ist viel zu klein um das alles aufzunehmen.

von Rolf M. (rmagnus)


Lesenswert?

= {0}; schrieb:
> Acell ist viel zu klein um das alles aufzunehmen.

So lange Number_as_String nur einstellig ist, reicht es gerade.

Kaj schrieb:
> Bartosz B. schrieb:
>> Ich werd niemals über 65535 Zeilen in
>> meiner Excel-Datei haben.
> Und wir werden niemals mehr als 640kB RAM brauchen... ;)

Excel selbst konnte lange Zeit nicht mehr als 65535 Zeilen.

von so einfach wie möglich, aber nicht einfacher (Gast)


Lesenswert?

Bartosz B. schrieb:
> strcat(Acell, "\x22"); // "
>       strcat(Acell, "A");
>       strcat(Acell, Number_as_String);
>       strcat(Acell, "\x22"); // "

wenn du sowieso mit sprintf arbeitest, dann pack doch alles rein:
1
   char str[32] = "";
2
   int x = 123;
3
4
   sprintf (str, "\x22""A%d\x22", x);
5
6
   puts (str);

von Kaj (Gast)


Lesenswert?

Rolf M. schrieb:
> Excel selbst konnte lange Zeit nicht mehr als 65535 Zeilen.
Stimmt, das ist richtig. Ich glaube seit Office 2010 kann Excel mehr, 
Mittlerweile sind es, glaube ich, 2^20 Zeilen.

von Dirk B. (dirkb2)


Lesenswert?

Bartosz B. schrieb:
> Weil ich dachte, dass das reicht. Ich werd niemals über 65535 Zeilen in
> meiner Excel-Datei haben.

Dein Acell ist nur für einstellige Zeilen ausreichend dimensioniert, da 
reicht auch ein char.
Da ist ein int mehr als ausreichend und kommt ohne viel gecaste aus.

int hat die native Größe auf dem jeweiligen System. Damit kann der 
Prozessor am Besten rechnen.

Und dafür gibt es dann auch uint16_least_t oder uint16_fastest_t.

Die xint00_t Typen sind in den wenigsten Fällen die richtige Wahl.

von 900ss D. (900ss)


Lesenswert?

Dirk B. schrieb:
> Die xint00_t Typen sind in den wenigsten Fällen die richtige Wahl.

Erklärung?

von Rolf M. (rmagnus)


Lesenswert?

900ss D. schrieb:
> Dirk B. schrieb:
>> Die xint00_t Typen sind in den wenigsten Fällen die richtige Wahl.
>
> Erklärung?

Weil sie eine feste Größe erzwingen. Das braucht man nur dort, wo man 
direkt mit Hardware-Registern oder anderen Systemen binär kommuniziert 
und daher ein bestimmtes Datenformat einhalten muss.

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> Weil sie eine feste Größe erzwingen.

Die aktuell existrierenden Implementierungen der Typen aus der stdint.h 
ist per typedef auf die Standard-POD-Typen. Es gibt im ganzen 
C/C++-Universum keine POD-Datentypen mit flexibler Länge.

Oliver

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Oliver S. schrieb:
> Rolf M. schrieb:
>> Weil sie eine feste Größe erzwingen.
>
> Die aktuell existrierenden Implementierungen der Typen aus der stdint.h
> ist per typedef auf die Standard-POD-Typen. Es gibt im ganzen
> C/C++-Universum keine POD-Datentypen mit flexibler Länge.

Außer [u]intXX_t-Typedefs sind sämtliche Standard-C-Typen 
plattformabhängig. int kann je nach Compiler z.B. 16, 24, 32 oder 64 Bit 
breit sein, oder auch jede andere Größe, die mindesten 16 Bit beträgt.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> int kann je nach Compiler z.B. 16, 24, 32 oder 64 Bit
> breit sein,

Wer plattformübergreifend für völlig exotische oder sonstwie abstruse 
Architekturen und Compiler programmieren muß, für den ist das ein Thema.

Und gerade dort wäre der Einsatz der xint_nnt-Typen für alles ausser 
banalen Schleifenindizes angesagt. Da weiß man wenigstens, was man hat.

Oliver

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Oliver S. schrieb:
> Die aktuell existrierenden Implementierungen der Typen aus der stdint.h
> ist per typedef auf die Standard-POD-Typen.

Und man weiß nicht, aus welchen Typen das gemacht wird.

Eigentlich möchte man ja nur, dass der erforderliche Wertebereich 
abgedeckt wird. Und da sind die fastest oder least Typen sinnvoller.

Für die Zwecke des TO ist aber ein int ausreichen groß, schnell und 
einfach.
(Der Thread steht in PC-Programmierung und es geht um Excel)

von 900ss D. (900ss)


Lesenswert?

Rolf M. schrieb:
> Weil sie eine feste Größe erzwingen

Die anderen Typen nutzen mindestens die Breite (Größe). Wo ist da der 
Vorteil?
Höchstens evtl. etwas Geschwindigkeit oder noch mehr?

Also ich weiß lieber was ich hab ;)

von Peter D. (peda)


Lesenswert?

Bartosz B. schrieb:
> Der Vorteil ist, dass man nicht itoa benutzen muss.

Was soll daran ein Vorteil sein, Funktionen nicht zu benutzen, die 
garantiert funktionieren und in der Regel besser optimiert sind, als 
alles Handgemachte.

Deine Funktion ist ja von hinten durch die Brust ins Auge und ruft 
snprintf doppelt auf, wozu?
Du meinst doch nicht ernsthaft, daß Deine Maschine abstürzt, wenn mal 
ein paar Byte mehr reserviert werden.
Im Gegenteil, das malloc ist sogar besonders teuer, da es zusätzliche 
Verwaltungsinformationen ablegen muß. Oftmals kann malloc daher eh keine 
Häppchen <16 Byte reservieren, "65535" benötigt aber nur 6.

Im einfachsten Fall legt der Aufrufer ein Array für 6 Byte an und 
übergibt dessen Adresse. Das erspart das ganze malloc/free Geraffel, 
geht also am schnellsten.
Und falls die Funktion mehrfach benötigt wird, kann man das Array weiter 
benutzen, d.h. man muß es nicht ständig neu anlegen.

Auch das handgemachte ins Ziel kopieren ist langsamer und aufwendiger 
als die Libfunktion strcpy() und natürlich schlechter lesbar. Jeder muß 
erstmal überlegen, wo ist der verdammte Haken, daß Du sie nicht 
verwendest.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.