Sto cercando di stampare tipi come off_t
e size_t
. Qual è il segnaposto corretto per printf()
questo è portatile ?
O c'è un modo completamente diverso di stampare quelle variabili?
Sto cercando di stampare tipi come off_t
e size_t
. Qual è il segnaposto corretto per printf()
questo è portatile ?
O c'è un modo completamente diverso di stampare quelle variabili?
Risposte:
Puoi usare z
per size_t e t
per ptrdiff_t come in
printf("%zu %td", size, ptrdiff);
Ma la mia manpage dice che alcune biblioteche più vecchie usavano un personaggio diverso da quello z
e ne scoraggia l'uso. Tuttavia, è standardizzato (dallo standard C99). Per chi 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 nella manpage di inttypes.h
.
Personalmente, vorrei solo lanciare i valori unsigned long
o long
come consiglia un'altra risposta. Se usi C99, puoi (e ovviamente, ovviamente) eseguire il cast verso unsigned long long
o long long
e utilizzare rispettivamente i formati %llu
o %lld
.
%zd
con a nonsize_t
è un comportamento definito a causa della mancata corrispondenza della firma (C99 7.19.6.1 # 9). Deve essere %zu
.
%zd
con un size_t
comportamento indefinito si ottenga da quel paragrafo o da qualsiasi altro. In effetti, la definizione di %z
in # 7 consente esplicitamente %d
con size_t
e il tipo con segno corrispondente e §6.2.5 # 9 consente esplicitamente l'uso di valori di tipi senza segno in cui è previsto il tipo con segno corrispondente, purché il valore sia un valore non negativo valido del tipo firmato.
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);
Vedi 7.19.6.1/7 nello standard C99 o la documentazione POSIX più conveniente dei codici di formattazione:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Se la tua implementazione non supporta quei codici di formattazione (ad esempio perché sei su C89), allora hai un po 'di problemi dal momento che AFAIK non ci sono tipi interi in C89 che hanno codici di formattazione e sono garantiti per essere grandi come questi tipi. Quindi devi fare qualcosa di specifico per l'implementazione.
Ad esempio se il tuo compilatore ha long long
e la tua libreria standard supporta %lld
, puoi aspettarti con sicurezza che servirà al posto di intmax_t
. In caso contrario, dovrai ricorrere a long
, il che fallirebbe su alcune altre implementazioni perché è troppo piccolo.
ssize_t
abbia le stesse dimensioni di size_t
, quindi il codice veramente portatile dovrebbe convertirlo intmax_t
e stamparlo %jd
come off_t
.
Per Microsoft, la risposta è diversa. VS2013 è ampiamente conforme a C99 ma "[t] he hh, j, z e prefissi di lunghezza non sono supportati." Per size_t "ovvero __int32 senza segno su piattaforme a 32 bit, __int64 senza segno su piattaforme a 64 bit" utilizzare il prefisso I (occhio di capitale) con l' identificatore di tipo o, u, x o X. Vedere le specifiche di dimensione VS2013
Per quanto riguarda off_t, è definito come lungo in VC \ include \ sys \ types.h.
off_t
è sempre long
quello lo renderebbe a 32 bit (anche Windows a 64 bit utilizza 32 bit per long
).
Quale versione di C stai usando?
In C90, la pratica standard consiste nel lanciare a lungo firmato o non firmato, come appropriato, e stampare di conseguenza. Ho visto% z per size_t, ma Harbison e Steele non lo menzionano sotto printf (), e in ogni caso ciò non ti aiuterebbe con ptrdiff_t o altro.
In C99, i vari tipi di _t vengono forniti con le loro macro printf, quindi qualcosa come "Size is " FOO " bytes."
io non conosco i dettagli, ma fa parte di un formato numerico abbastanza grande che include file.
Ti consigliamo di utilizzare le macro di formattazione da inttypes.h.
Vedi questa domanda: stringa di formato multipiattaforma per variabili di tipo size_t?
off_t
tipo è più grande di un puntatore su qualsiasi sistema a 32 bit che supporta file di grandi dimensioni (che è la maggior parte dei sistemi a 32 bit in questi giorni).
Guardando man 3 printf
su Linux, OS X e OpenBSD tutti mostrano il supporto %z
per size_t
e %t
per ptrdiff_t
(per C99), ma nessuno di questi menziona off_t
. I suggerimenti in natura offrono solitamente la %u
conversione per off_t
, che è "abbastanza corretta" per quanto ne so (entrambi unsigned int
e off_t
variano in modo identico tra i sistemi a 64 e 32 bit).
unsigned int
e 64 bit off_t
. Quindi il cast causerebbe la perdita di dati.
Ho visto questo post almeno due volte, perché la risposta accettata è difficile da ricordare per me (uso raramente z
o j
flag e non sembrano indipendenti dalla piattaforma ).
Lo standard non dice mai chiaramente la lunghezza esatta dei dati size_t
, quindi ti consiglio di controllare prima la lunghezza size_t
sulla tua piattaforma, quindi selezionarne una:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
E suggerisco di usare stdint
tipi invece di tipi di dati grezzi per coerenza.
%zu
può essere utilizzato per stampare size_t
valori. Non si dovrebbe assolutamente ricorrere all'uso di un identificatore uint32_t
/ uint64_t
format per stampare un size_t
, in quanto non esiste alcuna garanzia che tali tipi siano compatibili.
Per quanto ricordo, l'unico modo portatile per farlo è quello di trasmettere il risultato a "unsigned long int" e usarlo %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
non esiste nello standard C ++ ed è quindi intrinsecamente non portatile.
fopen
,fseek
ecc su Mac OS X.off_t
viene utilizzato per l'offset.