J'essaye d'imprimer des types comme off_t
et size_t
. Quel est l'espace réservé correct pour printf()
qui est portable ?
Ou y a-t-il une manière complètement différente d'imprimer ces variables?
c
portability
format-specifiers
Georg Schölly
la source
la source
fopen
,fseek
etc. sous Mac OS X.off_t
est utilisé pour le décalage.Réponses:
Vous pouvez utiliser
z
pour size_t ett
pour ptrdiff_t comme dansMais ma page de manuel indique que certaines bibliothèques plus anciennes utilisaient un caractère différent de celui-ci
z
et en déconseillent l'utilisation. Néanmoins, il est standardisé (par la norme C99). Pour ceuxintmax_t
etint8_t
destdint.h
et ainsi de suite, il y a des macros que vous pouvez utiliser, comme une autre réponse dit:Ils sont répertoriés dans la page de manuel de
inttypes.h
.Personnellement, je ferais simplement passer les valeurs
unsigned long
oulong
comme le recommande une autre réponse. Si vous utilisez C99, vous pouvez (et devriez, bien sûr) lancer versunsigned long long
oulong long
et utiliser le%llu
%lld
respectivement les formats ou .la source
%zd
avec asize_t
est un comportement indéfini en raison de l'incohérence de signature (C99 7.19.6.1 # 9). Ça doit être%zu
.%zd
unsize_t
obtient un comportement non défini de ce paragraphe ou de tout autre. En fait, la définition de%z
in # 7 autorise explicitement%d
avecsize_t
et le type signé correspondant, et §6.2.5 # 9 permet explicitement d'utiliser des valeurs de types non signés où le type signé correspondant est attendu, tant que la valeur est une valeur non négative valide du type signé.Pour imprimer
off_t
:Pour imprimer
size_t
:Pour imprimer
ssize_t
:Voir 7.19.6.1/7 dans la norme C99, ou la documentation POSIX plus pratique des codes de formatage:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Si votre implémentation ne prend pas en charge ces codes de formatage (par exemple parce que vous êtes sur C89), alors vous avez un petit problème car AFAIK il n'y a pas de types entiers dans C89 qui ont des codes de formatage et sont garantis aussi gros comme ces types. Vous devez donc faire quelque chose de spécifique à l'implémentation.
Par exemple, si votre compilateur a
long long
et que votre bibliothèque standard le prend en charge%lld
, vous pouvez vous attendre à ce que cela serve à la place deintmax_t
. Mais si ce n'est pas le cas, vous devrez vous rabattre surlong
, ce qui échouerait sur certaines autres implémentations car il est trop petit.la source
ssize_t
a la même taille quesize_t
, donc un code vraiment portable devrait le convertirintmax_t
et l'imprimer avec%jd
commeoff_t
.Pour Microsoft, la réponse est différente. VS2013 est en grande partie conforme à C99 mais "[l] es préfixes de longueur hh, j, z et t ne sont pas pris en charge." Pour size_t "c'est-à-dire __int32 non signé sur les plates-formes 32 bits, __int64 non signé sur les plates-formes 64 bits", utilisez le préfixe I (œil majuscule) avec le spécificateur de type o, u, x ou X. Voir la spécification de taille VS2013
Quant à off_t, il est défini comme long dans VC \ include \ sys \ types.h.
la source
off_t
c'est toujourslong
cela le rendrait 32 bits (même Windows 64 bits utilise 32 bits pourlong
).Quelle version de C utilisez-vous?
Dans C90, la pratique courante consiste à convertir en caractères longs signés ou non signés, selon le cas, et à imprimer en conséquence. J'ai vu% z pour size_t, mais Harbison et Steele ne le mentionnent pas sous printf (), et en tout cas cela ne vous aiderait pas avec ptrdiff_t ou autre.
Dans C99, les différents types _t sont livrés avec leurs propres macros printf, donc quelque chose comme
"Size is " FOO " bytes."
je ne connais pas les détails, mais cela fait partie d'un fichier d'inclusion de format numérique assez grand.la source
Vous voudrez utiliser les macros de mise en forme de inttypes.h.
Voir cette question: Chaîne de format multiplateforme pour les variables de type size_t?
la source
off_t
type est plus grand qu'un pointeur sur n'importe quel système 32 bits qui prend en charge de gros fichiers (ce qui est la plupart des systèmes 32 bits de nos jours).En regardant
man 3 printf
sur Linux, OS X et OpenBSD, tous montrent le support%z
poursize_t
et%t
pourptrdiff_t
(pour C99), mais aucun de ceux-ci ne le mentionneoff_t
. Les suggestions dans la nature offrent généralement la%u
conversion pouroff_t
, ce qui est "assez correct" pour autant que je sache (les deuxunsigned int
etoff_t
varient de la même manière entre les systèmes 64 bits et 32 bits).la source
unsigned int
et 64 bitsoff_t
. Ainsi, le casting entraînerait la perte de données.J'ai vu ce post au moins deux fois, car la réponse acceptée est difficile à retenir pour moi (j'utilise rarement
z
ou desj
drapeaux et ils ne semblent pas indépendants de la plate-forme ).La norme ne dit jamais clairement la longueur exacte des données de
size_t
, donc je vous suggère de vérifier d'abord la longueursize_t
sur votre plate-forme, puis de sélectionner l'une d'entre elles:Et je suggère d'utiliser des
stdint
types au lieu de types de données brutes pour la cohérence.la source
%zu
peut être utilisée pour imprimer dessize_t
valeurs. Il ne faut certainement pas recourir à un spécificateuruint32_t
/uint64_t
format pour imprimer unsize_t
, car il n'y a aucune garantie que ces types sont compatibles.Si je me souviens bien, la seule façon portable de le faire est de convertir le résultat en "unsigned long int" et de l'utiliser
%lu
.la source
long long
n'existe pas dans la norme C ++, et est donc intrinsèquement non portable.utilisez "% zo" pour off_t. (octal) ou "% zu" pour décimal.
la source