Sto cercando di stampare tipi come off_te 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_te size_t. Qual è il segnaposto corretto per printf() questo è portatile ?
O c'è un modo completamente diverso di stampare quelle variabili?
Risposte:
Puoi usare zper size_t e tper 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 ze ne scoraggia l'uso. Tuttavia, è standardizzato (dallo standard C99). Per chi intmax_te int8_tdi 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 longo longcome consiglia un'altra risposta. Se usi C99, puoi (e ovviamente, ovviamente) eseguire il cast verso unsigned long longo long longe utilizzare rispettivamente i formati %lluo %lld.
%zdcon a nonsize_t è un comportamento definito a causa della mancata corrispondenza della firma (C99 7.19.6.1 # 9). Deve essere %zu.
%zdcon un size_tcomportamento indefinito si ottenga da quel paragrafo o da qualsiasi altro. In effetti, la definizione di %zin # 7 consente esplicitamente %dcon size_te 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 longe 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_tabbia le stesse dimensioni di size_t, quindi il codice veramente portatile dovrebbe convertirlo intmax_te stamparlo %jdcome 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 longquello 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_ttipo è 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 printfsu Linux, OS X e OpenBSD tutti mostrano il supporto %zper size_te %tper ptrdiff_t(per C99), ma nessuno di questi menziona off_t. I suggerimenti in natura offrono solitamente la %uconversione per off_t, che è "abbastanza corretta" per quanto ne so (entrambi unsigned inte off_tvariano in modo identico tra i sistemi a 64 e 32 bit).
unsigned inte 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 zo jflag 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_tsulla tua piattaforma, quindi selezionarne una:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
E suggerisco di usare stdinttipi invece di tipi di dati grezzi per coerenza.
%zupuò essere utilizzato per stampare size_tvalori. Non si dovrebbe assolutamente ricorrere all'uso di un identificatore uint32_t/ uint64_tformat 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 longnon esiste nello standard C ++ ed è quindi intrinsecamente non portatile.
fopen,fseekecc su Mac OS X.off_tviene utilizzato per l'offset.