2010-07-02 10 views
81

Ich habe folgendesprintf Formatbezeich für uint32_t und size_t

size_t i = 0; 
uint32_t k = 0; 

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

erhalte ich die folgende Warnung beim Kompilieren:

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

Wenn ich diese mit Schiene lief ich folgendes bekam:

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

Vielen Dank für eine Beratung,

+1

C89 unterstützt 'uint32_t' nicht von' 'oder' ''; Wenn Sie diese Typen verwenden möchten, sollten Sie auf C89 aktualisieren. Als Erweiterung ist es wahrscheinlich, dass der GCC Ihnen erlaubt, sie zu verwenden, aber C89 hatte keine solche Unterstützung. –

+9

Und der offizielle C99-Format-Modifikator für 'size_t' ist 'z', wie in' "% zu" '. –

+1

http://stackoverflow.com/questions/1401526/how-to-use-printf-to-display-off-t-nlink-t-size-t-and-other-special-types –

Antwort

18

Klingt so, als ob Sie erwarten, dass size_t dasselbe ist wie unsigned long (möglicherweise 64 Bit), wenn es tatsächlich ein unsigned int (32 Bit) ist. Verwenden Sie in beiden Fällen %zu.

Ich bin jedoch nicht ganz sicher.

+1

Keine Warnungen beim Kompilieren.Ich bekomme jedoch die laufende Schiene: 1) printf (% u) erwartet unsigned int bekommt uint32_t: i 2) printf (% u) erwartet unsigned int wird size_t: k – ant2009

+0

Klingt wie Schiene wird nur pedantisch, dann. Wahrscheinlich werden die Namen der Typen im Quellcode entfernt und sie merken nicht, dass sie gleichwertig sind. Ich frage mich, was es mit @ Kenny ™ Antwort tun würde ... Es sollte sicherlich tragbarer sein. – Cogwheel

+3

Schiene macht eigentlich das Richtige. Nur weil "int32_t" auf Ihrem Compiler/Ihrer Plattform "int" ist, bedeutet das nicht, dass es auf einem anderen nicht "lang" ist. Gleiches gilt für 'size_t'. Es macht sich wirklich Mühe und tut ** mehr **, um diesen Portabilitätsfehler zu entdecken, da die einfache, natürliche Überprüfung darin besteht, den Typedef wie den Compiler zu respektieren. –

114

Versuchen

#include <inttypes.h> 
... 

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

Die z eine ganze Zahl von Länge gleich wie size_t darstellt, und das Makro PRIu32, defined in the C99 header inttypes.h stellt eine vorzeichenlose 32-Bit-Integer.

+0

Kompiliert ohne Warnungen. Aber Schiene mag es nicht. Nicht erkannter Formatcode:% zu. Und für den zweiten. Parse Fehler. (Hilfe zur Analyse von Fehlern finden Sie unter splinth-help parseerrors.) *** Kann nicht fortgesetzt werden. – ant2009

+3

@robUK: Heh. Ich schlage vor, dass Sie einen Fehler für die Schiene einreichen. – kennytm

+6

Dies ist die richtige Antwort. Obwohl meine persönliche Empfehlung ist, einfach zu z. 'printf ("% lu ", (unsigniert lang) i)'. Sonst landet man später wegen einer Typänderung im Stapel mit Warnungen. – Dummy00001

16

Wenn Sie nicht wollen, die PRI * Makros verwenden, einen anderen Ansatz ANY Integer-Typ für den Druck ist zu intmax_t oder uintmax_t und verwenden "%jd" oder %ju jeweils zu werfen. Dies ist besonders nützlich für POSIX-Typen (oder andere Betriebssysteme), für die keine PRI * -Makros definiert sind, z. B. off_t.

21

Alles, was benötigt wird, ist, dass die Formatbezeichner und die Typen übereinstimmen, und Sie können immer festlegen, dass dies der Fall ist. long mindestens 32 Bit, so %lu zusammen mit (unsigned long)k ist immer richtig:

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

size_t ist schwieriger, weshalb %zu in C99 aufgenommen. Wenn Sie das nicht verwenden können, behandeln Sie es wie 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 nicht die Formatangaben korrekt für die Art erhalten Sie vorbei, dann printf tun das Äquivalent des Feldes aus zu viel oder zu wenig Speicher. Solange Sie explizite Umwandlungen verwenden, um Typen zu vergleichen, ist es portabel.