In jeder halbwegs modernen C-Implementierung, "%zu"
ist der richtige Weg, um einen Wert des Typs size_t
:
printf("sizeof (int) = %zu\n", sizeof (int));
El "%zu"
wurde in der ISO C-Norm von 1999 hinzugefügt (und von der ISO C++-Norm von 2011 übernommen). Wenn Sie sich keine Gedanken über ältere Implementierungen machen müssen, können Sie jetzt aufhören zu lesen.
Wenn Ihr Code auf Implementierungen vor C99 portabel sein muss, können Sie den Wert in unsigned long
und verwenden "%lu"
:
printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));
Das ist nicht auf C99 oder später übertragbar, weil C99 die long long
y unsigned long long
und damit die Möglichkeit, dass size_t
ist breiter als unsigned long
.
Widerstehen Sie der Versuchung, die "%lu"
o "%llu"
ohne die Besetzung. Der Typ, der zur Implementierung von size_t
ist implementierungsabhängig, und wenn die Typen nicht übereinstimmen, ist das Verhalten undefiniert. Etwas wie printf("%lu\n", sizeof (int));
mag "funktionieren", ist aber keineswegs übertragbar.
Im Prinzip gilt Folgendes sollte alle möglichen Fälle abdecken:
#if __STDC_VERSION__ < 199901L
printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));
#else
printf("sizeof (int) = %zu\n", sizeof (int));
#endif
In der Praxis funktioniert dies jedoch nicht immer korrekt. __STD_VERSION__ >= 199901L
sollte garantieren, dass "%zu"
wird unterstützt, aber nicht alle Implementierungen sind notwendigerweise korrekt, zumal __STD_VERSION__
wird vom Compiler gesetzt und "%zu"
wird von der Laufzeitbibliothek implementiert. Zum Beispiel kann eine Implementierung mit teilweise Die C99-Unterstützung könnte Folgendes implementieren long long
und machen size_t
ein Typendefinition für unsigned long long
, aber keine Unterstützung "%zu"
. (Eine solche Implementierung würde wahrscheinlich nicht definieren __STDC_VERSION__
.)
Es wurde bereits darauf hingewiesen, dass Microsofts Implementierung 32-Bit unsigned long
und 64-Bit size_t
. Microsoft unterstützt "%zu"
, aber diese Unterstützung wurde erst relativ spät hinzugefügt. Auf der anderen Seite, Gießen zu unsigned long
ist nur dann ein Problem, wenn die jeweilige size_t
Wert zufällig übersteigt ULONG_MAX
was in der Praxis eher unwahrscheinlich ist.
Wenn Sie von einigermaßen modernen Implementierungen ausgehen können, verwenden Sie einfach "%zu"
. Wenn Sie ältere Implementierungen berücksichtigen müssen, finden Sie hier ein absurd portables Programm, das sich an verschiedene Konfigurationen anpassen lässt:
#include <stdio.h>
#include <limits.h>
int main(void) {
const size_t size = -1; /* largest value of type size_t */
#if __STDC_VERSION__ < 199901L
if (size > ULONG_MAX) {
printf("size is too big to print\n");
}
else {
printf("old: size = %lu\n", (unsigned long)size);
}
#else
printf("new: size = %zu\n", size);
#endif
return 0;
}
Eine Implementierung, die "Größe ist zu groß zum Drucken" ausgibt ( x86_64-w64-mingw32-gcc.exe -std=c90
unter Windows/Cygwin) unterstützt tatsächlich unsigned long long
als eine Erweiterung von C90, so dass Sie vielleicht in der Lage sein werden, die Vorteile davon zu nutzen -- aber ich kann mir eine Implementierung aus der Zeit vor C99 vorstellen, die die unsigned long long
unterstützt aber nicht "%llu"
. Und diese Implementierung unterstützt "%zu"
sowieso.
Ich habe die Erfahrung gemacht, dass ich nur drucken wollte size_t
Werte in schnellem Wegwerfcode, wenn ich eine Implementierung erforsche, und nicht in Produktionscode. In einem solchen Kontext ist es wahrscheinlich ausreichend, einfach das zu tun, was funktioniert.
(Die Frage bezieht sich auf C, aber ich werde erwähnen, dass in C++ std::cout << sizeof (int)
funktioniert in jeder Version der Sprache korrekt).