2009-02-25 15 views
121

Sto provando a stampare tipi come off_t e size_t. Qual è il segnaposto corretto per printf()che è portatile?Come devo stampare tipi come off_t e size_t?

Oppure c'è un modo completamente diverso di stampare quelle variabili?

+2

@devin: Credo di aver trovato quel tipo durante l'utilizzo di 'fopen',' fseek', ecc. Su Mac OS X. 'off_t' viene utilizzato per l'offset. –

risposta

87

È possibile utilizzare z per size_t e t per ptrdiff_t come in

printf("%zu %zd", size, ptrdiff); 

Ma la mia man dice qualche vecchia libreria utilizzato un carattere diverso rispetto z e scoraggia l'uso di esso. Tuttavia, è standardizzato (secondo lo standard C99). Per coloro 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); 

Essi sono elencati nel suo manuale inttypes.h.

Personalmente, vorrei semplicemente trasmettere i valori a unsigned long o long come suggerito da un'altra risposta. Se si utilizza C99, è possibile (e dovrebbe, ovviamente) trasmettere a unsigned long long o long long e utilizzare rispettivamente i formati %llu o %lld.

+0

Poiché PRId32 non include lo specificatore di formato%, non dovrebbe essere 'printf (" valore:% "PRId32, some_int32_t);' –

+1

off_t è in realtà un long firmato lungo il mio sistema. –

+0

sì per i valori firmati che dovrai convertire a lungo o lungo. quest'ultimo tipo non esiste nel C++ corrente, ma la prossima versione lo include. specialmente se lavori con posix e include alcuni tipi come off_t che hanno dimensioni grandi, devi stare attento. –

3

Quale versione di C stai utilizzando?

In C90, lo standard è quello di trasmettere a firma o non firmata a lungo, a seconda dei casi, 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 può aiutare con ptrdiff_t o qualsiasi altra cosa.

In C99, i vari tipi _t sono dotati di macro printf, quindi qualcosa come "Size is " FOO " bytes." non conosco i dettagli, ma fa parte di un file numerico di formato abbastanza grande.

+0

Quale edizione di H & S - la quinta quasi certamente la menziona ... –

+0

Quarta edizione - dovrei aggiornare? –

-3

Come ricordo, l'unico modo portatile per farlo è quello di trasmettere il risultato a "unsigned long int" e utilizzare %lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int)); 
+1

Dovrebbe essere "% lu", in quanto il modificatore di lunghezza dovrebbe arrivare prima della conversione. – dwc

+1

off_t ad esempio è un lungo firmato. –

+2

Non è portatile. – vy32

1

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. I suggerimenti in natura solitamente offrono la conversione %u per off_t, che è "abbastanza corretta" per quanto posso dire (sia unsigned int che off_t variano in modo identico tra i sistemi a 64 e 32 bit).

+1

Il mio sistema (OS X) ha 'unsigned int' a 32 bit e' off_t' a 64 bit. Quindi il cast causerebbe la perdita di dati. –

3

Dovrai utilizzare le macro di formattazione di inttypes.h.

Vai a questa domanda: Cross platform format string for variables of type size_t?

+4

Non risponde come formattare off_t. – stepancheg

+0

Supponendo che off_t sia un int firmato, con dimensioni del puntatore (non so quale sia la definizione precisa) come ptrdiff_t, allora useresti PRIdPTR o PRIiPTR. –

+10

Il tipo 'off_t' è più grande di un puntatore su qualsiasi sistema a 32 bit che supporta file di grandi dimensioni (che attualmente è la maggior parte dei sistemi a 32 bit). –

-8

uso "% zo" per off_t. (ottale) o "% zu" per decimale.

+4

% z è per size_t not off_t – Draemon

+0

Perché dovresti volere l'offset del file in ottale? – poolie

84

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ù comoda 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 grandi come questi tipi. Quindi devi fare qualcosa di specifico per l'implementazione.

Ad esempio se il compilatore dispone di long long e la libreria standard supporta %lld, è possibile attendersi che funzioni al posto di intmax_t. Ma se così non fosse, dovrai ricorrere a long, che fallirebbe in alcune altre implementazioni perché è troppo piccolo.

+0

Questa è di gran lunga la risposta migliore, mi sarei dimenticato di usare% zu per size_t senza segno. E trasmettere a intmax_t è un'ottima soluzione per qualsiasi cosa off_t sia su qualsiasi piattaforma. –

+0

POSIX non garantisce che 'ssize_t' abbia le stesse dimensioni di' size_t', quindi il codice veramente portatile dovrebbe convertirlo in 'intmax_t' e stampare con'% jd' come 'off_t'. – nwellnhof

-5

Si prega di utilizzare% lu. Off_t non è firmato a lungo.

+4

Avete qualche specifica * che garantisca * questo? Solo perché qualcosa sembra essere vero per un determinato OS del compilatore/target non significa che sia sempre vero. – CodesInChaos

+1

Questo, e sembra che le definizioni varino, ma intuitivamente mi aspetto che qualsiasi implementazione sana di un offset sia un tipo firmato, per ovvi motivi. –

5

Per Microsoft, la risposta è diversa. VS2013 è ampiamente compatibile con C99 ma "[i] i prefissi hh, j, z e t non sono supportati." Per size_t "cioè __int32 non firmato su piattaforme a 32 bit, __int64 non firmato su piattaforme a 64 bit" l'uso del prefisso I (occhio del capitale) con indicatore di tipo o, u, x, o X. See VS2013 Size specification

Per quanto riguarda off_t , è definito come lungo in VC \ include \ sys \ types.h.

+0

Nota se 'off_t' è sempre' long' che lo renderebbe a 32 bit (anche Windows a 64 bit usa 32 bit per 'long'). – sourcejedi

-2

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 non sembra platform independant).

Il standard mai dice chiaramente l'esatta lunghezza dei dati di size_t, quindi vi suggerisco di dovrebbe innanzitutto verificare la lunghezza size_t sulla 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 stdint tipi invece di tipi di dati non elaborati per coerenza.

+0

Per C99 e C11, lo standard afferma esplicitamente che '% zu' può essere usato per stampare i valori di' size_t'. Uno dovrebbe * sicuramente non * ricorrere all'utilizzo di un identificatore di formato 'uint32_t' /' uint64_t' per stampare un 'size_t', in quanto non vi è alcuna garanzia che quei tipi siano compatibili. – Sebivor