Indépendant de la plate-forme size_t Spécificateurs de format dans c?

86

Je veux imprimer une variable de type size_ten C mais il semble qu'elle size_tsoit aliasée avec différents types de variables sur différentes architectures. Par exemple, sur une machine (64 bits), le code suivant ne renvoie aucun avertissement:

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

mais sur mon autre ordinateur (32 bits), le code ci-dessus produit le message d'avertissement suivant:

avertissement: le format '% ld' attend le type 'long int *', mais l'argument 3 a le type 'size_t *'

Je soupçonne que cela est dû à la différence de taille du pointeur, de sorte que sur ma machine 64 bits size_test aliasé sur un long int( "%ld"), alors que sur ma machine 32 bits size_test aliasé sur un autre type.

Existe-t-il un spécificateur de format spécifiquement pour size_t?

Ethan Heilman
la source
Votre message d'avertissement ne correspond pas au code. L'avertissement mentionne des pointeurs, votre code n'en a pas. En avez-vous retiré quelque &part?
Jens
Des pointeurs? Non, je ne reçois aucun avertissement sur les pointeurs, en fait, en fonction de la machine sur laquelle j'exécute ce code, parfois je ne reçois aucun avertissement. Essayez le code de test suivant: #include <stdio.h> int main () {size_t size = 1; printf ("la taille est% ld", taille); return 0; }
Ethan Heilman
1
@EthanHeilman Il fait référence au fait que vos avertissements indiquent warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'quand cela devrait probablement être le cas warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'. Utilisiez-vous peut-être à la scanf()place lorsque vous avez reçu ces avertissements?
RastaJedi
Copie
phuclv

Réponses:

123

Oui: utilisez le zmodificateur de longueur:

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

Les autres modificateurs de longueur disponibles sont hh(pour char), h(pour short), l(pour long), ll(pour long long), j(pour intmax_t), t(pour ptrdiff_t) et L(pour long double). Voir §7.19.6.1 (7) de la norme C99.

Adam Rosenfield
la source
quelle est la différence entre zd et zu? J'obtiens que zd est décimal, mais est-il signé, si oui, comment zd étant signé affecte-t-il les choses.
Ethan Heilman
1
C'est la différence entre a size_tet an ssize_t; ce dernier est rarement utilisé.
Adam Rosenfield
26
Bon, donc dans ce cas, vous devriez utiliser %zu, car l'argument n'est pas signé.
caf
Les autres options disponibles sont expliquées dans la page de manuel printf: linux.die.net/man/3/printf
INS
9
@detly: Non, le zmodificateur de longueur ne fait pas partie de C89 / C90. Si vous visez un code compatible C89, le mieux que vous puissiez faire est de convertir unsigned longet d'utiliser le lmodificateur de longueur à la place, par exemple printf("the size is %lu\n", (unsigned long)size);; la prise en charge à la fois de C89 et de systèmes avec une size_ttaille supérieure longest plus délicate et nécessiterait l'utilisation d'un certain nombre de macros de préprocesseur.
Adam Rosenfield
45

Oui il y a. Il est %zu(comme spécifié dans ANSI C99).

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

Notez que ce size_tn'est pas signé, donc %lddouble faux: mauvais modificateur de longueur et mauvais spécificateur de conversion de format. Au cas où vous vous poseriez la question, %zdc'est pour ssize_t(qui est signé).

maxschlepzig
la source
1

MSDN , indique que Visual Studio prend en charge le préfixe «I» pour le code portable sur les plates-formes 32 et 64 bits.

size_t size = 10;
printf("size is %Iu", size);
Arkantos
la source
6
il est spécifique à MS, ce qui n'est pas conforme à la norme, donc ce n'est pas indépendant de la plate-forme
phuclv
@phuclv En effet. Et si cela dit vraiment - comme la réponse le suggère - «portable», c'est encore pire que je n'ai jamais connu la SP. Non pas que cela me surprendrait ... Je ne suis pas du genre à voter parce que quelqu'un a fait l'effort d'essayer de répondre à quelque chose, mais cette réponse est tout simplement fausse. Ah, je pense que je comprends l'idée ici en «portable». Cela doit dire que cela fonctionne à la fois pour 32 bits et 64 bits. Mais bien sûr que ce serait le cas.
Pryftan du