printf-Formatbezeichner für uint32_t und size_t

Lesezeit: 5 Minuten

Benutzeravatar von ant2009
Ameise2009

Ich habe folgendes

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

Beim Kompilieren bekomme ich folgende Warnung:

format ‘%lu’ expects type ‘long unsigned int’, but argument has type ‘uint32_t’

Als ich dies mit Splint ausgeführt habe, habe ich Folgendes erhalten:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Vielen Dank für jeden Rat,

  • C89 wird nicht unterstützt uint32_t aus <stdint.h> oder <inttypes.h>; Wenn Sie diese Typen verwenden möchten, sollten Sie auf C89 aktualisieren. Als Erweiterung ist es wahrscheinlich, dass GCC Ihnen erlaubt, sie zu verwenden, aber C89 hatte keine solche Unterstützung.

    – Jonathan Leffler

    3. Juli 2010 um 18:05 Uhr

  • Und der offizielle C99-Formatmodifikator für size_t ist ‘z’, wie in "%zu".

    – Jonathan Leffler

    3. Juli 2010 um 18:07 Uhr

  • stackoverflow.com/questions/1401526/…

    – Ciro Santilli OurBigBook.com

    24. Oktober 2015 um 19:50 Uhr

  • Ich glaube, die Antwort von @kenny ist am besten für uint32_taber es fehlt size_t. Die Antwort von @ u0b34a0f6ae enthält beides.

    – jww

    19. Oktober 2016 um 4:25 Uhr

  • 2. Erwähnung von C89 im 1. Kommentar von Jonathan Leffler sollte C99 sein

    – bph

    19. Juli 2017 um 20:20 Uhr

Versuchen

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

Das z steht für eine ganze Zahl mit der gleichen Länge wie size_tund die PRIu32 Makro, im C99-Header definiert inttypes.hstellt eine 32-Bit-Ganzzahl ohne Vorzeichen dar.

  • @robUK: Heh. Ich schlage vor, Sie melden einen Fehler für Splint.

    – kennytm

    2. Juli 2010 um 19:04 Uhr

  • Dies ist die richtige Antwort. Obwohl meine persönliche Empfehlung ist, einfach zu werfen, z printf( "%lu", (unsigned long )i ). Sonst landet man später wegen einer Typänderung in einem Haufen Warnungen im ganzen Code.

    – Dummy00001

    2. Juli 2010 um 19:54 Uhr

  • Dies ist die richtige Antwort. Ich stimme KennyTM zu, einen Bug für Splint einzureichen. Übrigens ist “%zu” das richtige Format für size_t. Sie benötigen keines der PRI*-Makros zum Drucken von size_t.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    3. Juli 2010 um 14:08 Uhr

  • Wenn ich mich richtig erinnere, ist %zu C99, und in der Frage schrieb er ‘C89’.

    – Alkohol

    15. Oktober 2013 um 11:37 Uhr


  • @alcor ja, er hat C89 gesetzt (anscheinend das gcc-Compiler-Flag, das er verwendet), aber er verwendet uint32_t es ist also eigentlich C99-Code und sollte als solcher kompiliert werden.

    – Colin D. Bennett

    24. Oktober 2013 um 16:32 Uhr

Benutzeravatar von Cogwheel
Zahnrad

Klingt, als würden Sie erwarten size_t gleich sein wie unsigned long (evtl. 64 Bit) wenn es eigentlich eine ist unsigned int (32 Bit). Versuchen Sie es mit %zu in beiden Fällen.

Ganz sicher bin ich mir aber nicht.

  • Keine Warnungen beim Kompilieren. Wenn ich jedoch splint ausführe, erhalte ich Folgendes: 1) printf (%u) erwartet unsigned int bekommt uint32_t: i 2) printf (%u) erwartet unsigned int bekommt size_t: k

    – Ameise2009

    2. Juli 2010 um 18:45 Uhr

  • Klingt also so, als wäre Splint nur pedantisch. Es geht wahrscheinlich von den Namen der Typen im Quellcode aus und erkennt nicht, dass sie gleichwertig sind. Ich frage mich, was es mit der Antwort von @KennyTM machen würde … Es sollte sicherlich tragbarer sein.

    – Zahnrad

    2. Juli 2010 um 18:49 Uhr


  • Splint macht eigentlich das Richtige. Nur weil int32_t ist zufälligerweise int auf Ihrem Compiler/Plattform bedeutet nicht, dass dies möglicherweise nicht der Fall ist long übereinander. Das gleiche für size_t. Es geht tatsächlich aus dem Weg und tut mehr Arbeiten Sie daran, diesen Portabilitätsfehler zu erkennen, da die einfache, natürliche Überprüfung darin bestehen würde, nur die Typedef zu berücksichtigen, wie es der Compiler tut.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    3. Juli 2010 um 17:18 Uhr

  • -1, tut mir leid, es ist nicht tragbar. Alles, was benötigt wird, ist, dass die Formatbezeichner und die Typen übereinstimmen, und Sie können immer umwandeln, um dies wahr zu machen. long ist mindestens 32bit, also %lu zusammen mit (unsigned long)k ist immer richtig. size_t ist schwieriger, weshalb %zu wurde in C99 hinzugefügt. Wenn Sie das nicht verwenden können, dann behandeln Sie es genauso k (long ist der größte Typ in C89, size_t ist sehr unwahrscheinlich, dass sie größer ist).

    – u0b34a0f6ae

    8. November 2011 um 21:32 Uhr


Alles, was benötigt wird, ist, dass die Formatbezeichner und die Typen übereinstimmen, und Sie können immer umwandeln, um dies wahr zu machen. long ist mindestens 32 Bit, also %lu zusammen mit (unsigned long)k ist immer richtig:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_t ist schwieriger, weshalb %zu wurde in C99 hinzugefügt. Wenn Sie das nicht verwenden können, dann behandeln Sie es genauso k (long ist der größte Typ in C89, size_t ist sehr unwahrscheinlich, größer zu sein).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Wenn Sie die Formatbezeichner für den Typ, den Sie übergeben, nicht korrekt erhalten, dann printf entspricht dem Lesen von zu viel oder zu wenig Speicher aus dem Array. Solange Sie explizite Umwandlungen verwenden, um Typen abzugleichen, ist es portabel.

Wenn Sie die PRI*-Makros nicht verwenden möchten, ein anderer Ansatz zum Drucken IRGENDEIN Integer-Typ ist umzuwandeln intmax_t oder uintmax_t und verwenden "%jd" oder %ju, beziehungsweise. Dies ist beispielsweise besonders nützlich für POSIX-Typen (oder andere Betriebssysteme), für die keine PRI*-Makros definiert sind off_t.

1422610cookie-checkprintf-Formatbezeichner für uint32_t und size_t

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy