Plattformunabhängige size_t Formatbezeichner in c?

86

Ich möchte eine Variable vom Typ size_tin C ausdrucken, aber es scheint, dass size_tsie auf verschiedene Variablentypen auf verschiedenen Architekturen ausgerichtet ist. Auf einem Computer (64-Bit) gibt der folgende Code beispielsweise keine Warnungen aus:

size_t size = 1;
printf("the size is %ld", size);

Auf meinem anderen Computer (32-Bit) erzeugt der obige Code jedoch die folgende Warnmeldung:

Warnung: Das Format '% ld' erwartet den Typ 'long int *', aber Argument 3 hat den Typ 'size_t *'.

Ich vermute, dass dies auf die unterschiedliche size_tZeigergröße zurückzuführen ist , sodass auf meinem 64-Bit-Computer ein Alias ​​für a long int( "%ld") erfolgt, während auf meinem 32-Bit-Computer size_tein Alias ​​für einen anderen Typ erfolgt.

Gibt es einen speziellen Formatbezeichner für size_t?

Ethan Heilman
quelle
Ihre Warnmeldung stimmt nicht mit dem Code überein. Die Warnung erwähnt Zeiger, Ihr Code hat keine. Hast du &irgendwo welche entfernt?
Jens
Zeiger? Nein, ich erhalte keine Warnungen zu Zeigern. Je nachdem, auf welchem ​​Computer ich diesen Code ausführe, erhalte ich manchmal überhaupt keine Warnungen. Versuchen Sie den folgenden Testcode: #include <stdio.h> int main () {size_t size = 1; printf ("die Größe ist% ld", Größe); return 0; }
Ethan Heilman
1
@EthanHeilman Er verweist darauf , dass Ihre Warnungen sagen , warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'wenn es wahrscheinlich soll sagen werden warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'. Haben Sie vielleicht scanf()stattdessen verwendet, als Sie diese Warnungen erhielten?
RastaJedi

Antworten:

123

Ja: Verwenden Sie den zLängenmodifikator:

size_t size = sizeof(char);
printf("the size is %zu\n", size);  // decimal size_t ("u" for unsigned)
printf("the size is %zx\n", size);  // hex size_t

Die anderen verfügbaren Längenmodifikatoren sind hh(für char), h(für short), l(für long), ll(für long long), j(für intmax_t), t(für ptrdiff_t) und L(für long double). Siehe §7.19.6.1 (7) des C99-Standards.

Adam Rosenfield
quelle
Was ist der Unterschied zwischen zd und zu? Ich verstehe, dass zd dezimal ist, aber signiert ist. Wenn ja, wie wirkt sich das Signieren von zd auf die Dinge aus?
Ethan Heilman
1
Es ist der Unterschied zwischen a size_tund an ssize_t; Letzteres wird selten verwendet.
Adam Rosenfield
26
Richtig, in diesem Fall sollten Sie also verwenden %zu, da das Argument nicht signiert ist.
Café
Die anderen verfügbaren Optionen werden auf der Seite des printf-Handbuchs erläutert: linux.die.net/man/3/printf
INS
9
@detly: Nein, der Längenmodifikator zist nicht Teil von C89 / C90. Wenn Sie C89-kompatiblen Code anstreben, können Sie ihn am besten umwandeln unsigned longund lstattdessen den Längenmodifikator verwenden, z printf("the size is %lu\n", (unsigned long)size);. Die Unterstützung von C89 und Systemen mit size_tgrößeren als longist schwieriger und würde die Verwendung einer Reihe von Präprozessormakros erfordern.
Adam Rosenfield
45

Ja da ist. Dies ist %zu(wie in ANSI C99 angegeben).

size_t size = 1;
printf("the size is %zu", size);

Beachten Sie, dass dies size_tohne Vorzeichen ist und %lddaher doppelt falsch ist: falscher Längenmodifikator und falscher Formatkonvertierungsspezifizierer. Falls Sie sich fragen, %zdist für ssize_t(was signiert ist).

maxschlepzig
quelle
1

Laut MSDN unterstützt Visual Studio das Präfix "I" für Code, der auf 32- und 64-Bit-Plattformen portierbar ist.

size_t size = 10;
printf("size is %Iu", size);
Arkantos
quelle
6
Es ist MS-spezifisch, was nicht standardkonform ist, also nicht plattformunabhängig
phuclv
@phuclv In der Tat. Und wenn es wirklich heißt - wie die Antwort schon sagt - "tragbar", ist es noch schlimmer, als ich jemals über MS wusste. Nicht, dass es mich überraschen würde ... Ich bin nicht derjenige, der abstimmt, weil sich jemand die Mühe gemacht hat, etwas zu beantworten, aber diese Antwort ist einfach falsch. Ah, ich glaube, ich verstehe die Idee hier in "tragbar". Es muss gesagt werden, dass es sowohl für 32-Bit als auch für 64-Bit funktioniert. Aber natürlich würde es.
Pryftan