Come dovrei stampare tipi come off_t e size_t?
-
06-09-2019 - |
Domanda
Sto cercando di stampare tipi come off_t
e size_t
. Qual è il segnaposto corretta per printf()
che è portatile
O c'è un modo completamente diverso per stampare le variabili?
Soluzione
È possibile utilizzare z
per size_t e t
per ptrdiff_t come in
printf("%zu %td", size, ptrdiff);
Ma la mia man dice qualche vecchia libreria utilizzato un carattere diverso rispetto z
e scoraggia l'uso di esso. Tuttavia, è standardizzato (dallo standard C99). Per quei intmax_t
e int8_t
di stdint.h
e così via, ci sono le macro è possibile utilizzare, come un'altra risposta ha detto:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Sono elencati nel suo manuale inttypes.h
.
Personalmente, vorrei solo lanciare i valori unsigned long
o long
come un'altra risposta raccomanda. Se si utilizza C99, allora si può (e si deve, naturalmente) il cast unsigned long long
o long long
e utilizzare i formati %llu
o %lld
rispettivamente.
Altri suggerimenti
Per stampare off_t
:
printf("%jd\n", (intmax_t)x);
Per stampare size_t
:
printf("%zu\n", x);
Per stampare ssize_t
:
printf("%zd\n", x);
Vedere 7.19.6.1/7 nello standard C99, oppure il più conveniente documentazione POSIX dei codici di formattazione:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Se l'implementazione non supporta i codici di formattazione (ad esempio perché si è in C89), allora avete un po 'un problema dal momento che per quanto ne so non ci sono tipi interi in C89 che hanno codici di formattazione e sono garantiti per essere grande come questi tipi. Quindi è necessario fare qualcosa di implementazione specifici.
Per esempio se il compilatore ha long long
e la vostra libreria standard supporta %lld
, si può tranquillamente aspettare che servirà al posto di intmax_t
. Ma se così non fosse, si dovrà ricadere long
, che fallire su alcuni altre implementazioni perché è troppo piccolo.
Per Microsoft, la risposta è diversa. VS2013 è in gran parte C99 compatibile, ma "[l] a HH, J, Z, e t prefissi di lunghezza non sono supportati." per size_t "Cioè, __int32 unsigned su piattaforme a 32 bit, __int64 non firmato su piattaforme a 64 bit" l'uso del prefisso I (capitale occhio) con indicatore di tipo o, u, x, o X. Vedi Formato specifica VS2013
Per quanto riguarda off_t, si è definito il più a lungo in VC \ include sys \ types.h \.
Quale versione di C stai usando?
Nel C90, la pratica standard è di lanciare a firmato o unsigned long, a seconda dei casi, e la stampa di conseguenza. Ho visto% z per size_t, ma Harbison e Steele Non c'è di che sotto printf (), e in ogni caso non si farebbe aiutare con ptrdiff_t o qualsiasi altra cosa.
In C99, i vari tipi _t vengono con i loro macro printf, in modo da qualcosa come "Size is " FOO " bytes."
non so i dettagli, ma questo fa parte di un gran formato numerico include file.
Ti consigliamo di utilizzare le macro di formattazione da inttypes.h.
Vedere questa domanda: Croce stringa di formato piattaforma per le variabili di tipo size_t?
Guardando man 3 printf
su Linux, OS X, e OpenBSD tutto il supporto spettacolo per %z
per size_t
e %t
per ptrdiff_t
(per C99), ma nessuno di quelli menzione off_t
. Suggerimenti in the wild di solito offrono la conversione %u
per off_t
, che è "abbastanza corretto", per quanto posso dire (sia unsigned int
e off_t
variano in modo identico tra i sistemi a 64-bit e 32-bit).
Ho visto questo post almeno due volte, perché la risposta accettata è difficile per ricordare per me (io uso raramente z
o j
bandiere e sono sembra non piattaforma indipendente ).
Il serie mai dice chiaramente l'esatta lunghezza dei dati di size_t
, quindi vi suggerisco di dovrebbe innanzitutto verificare la lunghezza su size_t
la vostra piattaforma quindi selezionare uno di loro:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
E io suggerisco di usare tipi stdint
invece di tipi di dati grezzi per la consistenza.
Se ricordo bene, l'unico modo portatile per farlo, è quello di gettare il risultato di "long int unsigned" e utilizzare %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
utilizzare "% zo" per off_t. (Ottale) o "zu%", per decimali.