536 Stimmen

Wie kann man eine size_t-Variable portabel mit der printf-Familie drucken?

Ich habe eine Variable vom Typ size_t und ich möchte es drucken mit printf() . Welchen Formatspezifikator muss ich verwenden, um es portabel zu drucken?

Auf einem 32-Bit-Rechner, %u scheint richtig zu sein. Ich habe kompiliert mit g++ -g -W -Wall -Werror -ansi -pedantic und es gab keine Warnung. Aber wenn ich den Code auf einem 64-Bit-Rechner kompiliere, wird eine Warnung ausgegeben.

size_t x = <something>;
printf("size = %u\n", x);

warning: format '%u' expects type 'unsigned int', 
    but argument 2 has type 'long unsigned int'

Die Warnung verschwindet, wie erwartet, wenn ich das in %lu .

Die Frage ist, wie kann ich den Code so schreiben, dass er sowohl auf 32- als auch auf 64-Bit-Maschinen warnfrei kompiliert werden kann?

Edit: Als Workaround könnte eine Lösung darin bestehen, die Variable in eine Ganzzahl zu "casten", die groß genug ist, sagen wir unsigned long und drucken mit %lu . Das würde in beiden Fällen funktionieren. Ich bin auf der Suche, ob es eine andere Idee gibt.

-1voto

Kylotan Punkte 18135

Werden Sie gewarnt, wenn Sie eine 32-Bit-Ganzzahl ohne Vorzeichen an ein %lu-Format übergeben? Das sollte kein Problem sein, da die Konvertierung wohldefiniert ist und keine Informationen verloren gehen.

Ich habe gehört, dass einige Plattformen Makros in <inttypes.h> die Sie in das Format-String-Literal einfügen können, aber ich sehe diesen Header nicht in meinem Windows-C++-Compiler, was bedeutet, dass er möglicherweise nicht plattformübergreifend ist.

-3voto

peterchen Punkte 39679

C99 definiert "%zd" etc. dafür. (Dank an die Kommentatoren) In C++ gibt es dafür keinen portablen Formatspezifizierer - Sie könnte utilice %p , die in diesen beiden Szenarien funktionieren würde, aber auch nicht portabel ist und den Wert in Hexadezimalzahlen angibt.

Verwenden Sie alternativ ein Streaming (z. B. stringstream) oder einen sicheren printf-Ersatz wie Boost-Format . Ich verstehe, dass dieser Ratschlag nur von begrenztem Nutzen ist (und C++ voraussetzt). (Wir haben einen ähnlichen Ansatz verwendet, der für unsere Bedürfnisse bei der Implementierung der Unicode-Unterstützung geeignet war).

Das grundsätzliche Problem für C ist, dass printf, das ein Ellipsis verwendet, vom Design her unsicher ist - es muss die Größe des zusätzlichen Arguments aus den bekannten Argumenten bestimmen, also kann es nicht so eingestellt werden, dass es "whatever you got" unterstützt. Wenn Ihr Compiler also keine proprietären Erweiterungen implementiert, haben Sie Pech.

-4voto

pixelbeat Punkte 28985

Auf einigen Plattformen und für einige Typen gibt es spezielle printf-Konvertierungsspezifizierer, aber manchmal muss man auf das Casting auf größere Typen zurückgreifen.

Ich habe dieses schwierige Problem hier mit Beispielcode dokumentiert: http://www.pixelbeat.org/programming/gcc/int_types/ und aktualisieren sie regelmäßig mit Informationen über neue Plattformen und Typen.

-9voto

Andre Punkte 172

Wenn Sie den Wert eines size_t als String ausgeben möchten, können Sie dies tun:

char text[] = "Lets go fishing in stead of sitting on our but !!";
size_t line = 2337200120702199116;

/* on windows I64x or I64d others %lld or %llx if it works %zd or %zx */
printf("number: %I64d\n",*(size_t*)&text);
printf("text: %s\n",*(char(*)[])&line);

Ergebnis ist:

Nummer: 2337200120702199116

Text: Lasst uns angeln gehen, anstatt auf unserem Hintern zu sitzen!

Bearbeiten: Lesen Sie die Frage wegen der Stimmen nach unten ich festgestellt, sein Problem ist nicht %llu oder %I64d aber die size_t-Typ auf verschiedenen Maschinen siehe diese Frage https://stackoverflow.com/a/918909/1755797
http://www.cplusplus.com/reference/cstdio/printf/

size_t ist unsigned int auf einem 32bit-Rechner und unsigned long long int auf einem 64bit-Rechner
aber %ll erwartet immer einen unsigned long long int.

size_t variiert in der Länge auf verschiedenen Betriebssystemen, während %llu die gleiche ist

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X