2009-09-09 16 views
26

Nel mio programma, ho Stat i file desiderati e inviare i dati sopra. I campi di una statistica struct sono tutti i tipi speciali:Come usare printf per visualizzare off_t, nlink_t, size_t e di altri tipi speciali?

struct stat { 
    dev_t  st_dev;  /* ID of device containing file */ 
    ino_t  st_ino;  /* inode number */ 
    mode_t st_mode; /* protection */ 
    nlink_t st_nlink; /* number of hard links */ 
    uid_t  st_uid;  /* user ID of owner */ 
    gid_t  st_gid;  /* group ID of owner */ 
    dev_t  st_rdev; /* device ID (if special file) */ 
    off_t  st_size; /* total size, in bytes */ 
    blksize_t st_blksize; /* blocksize for file system I/O */ 
    blkcnt_t st_blocks; /* number of 512B blocks allocated */ 
    time_t st_atime; /* time of last access */ 
    time_t st_mtime; /* time of last modification */ 
    time_t st_ctime; /* time of last status change */ 
}; 

Il codice rilevante per la mia domanda seguente:

len = snprintf(statbuf, STAT_BUFFER_SIZE, 
    "%crwxrwxrwx %lu %u %u %lld %s %s\r\n", 
    S_ISDIR(filestats.st_mode) ? 'd' : '-', 
    (unsigned long) filestats.st_nlink, 
    filestats.st_uid, 
    filestats.st_gid, 
    (unsigned long long) filestats.st_size, 
    date, 
    filename); 

Come faccio a stampare questi tipi in modo portatile ed efficiente? All'inizio l'ho fatto senza calcoli indovinando gli specificatori di formato corretti. Oltre ad essere una fastidiosa abitudine di programmazione, questo significava anche che il mio codice non funzionava su un sistema a 32 bit. Ora con i cast sembra funzionare, ma su quante piattaforme?

+0

specifico per clock_t: http://stackoverflow.com/questions/1083142/what-s-the-correct-way-to-use-printf-to-print-a-clock-t –

+0

Per '__uint128': http://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc –

risposta

25

non c'è un modo completamente portatile per farlo, ed è un fastidio.

C99 fornisce un meccanismo per tipi integrati come size_t con la notazione %zu (e ci sono alcuni qualificatori aggiuntivi simili).

Esso fornisce anche l'<inttypes.h> intestazione con le macro come PRIX32 per definire la qualificazione corretta per stampare una costante esadecimale a 32 bit (in questo caso):

printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t); 

Per i tipi definiti dal sistema (ad esempio quelli definiti da POSIX), AFAIK, non c'è un buon modo per gestirli. Quindi, quello che faccio è prendere una supposizione che vola a una conversione 'sicuro' quindi stampare di conseguenza, tra cui il cast, che è quello che illustrare la questione. È frustrante, ma non c'è modo migliore di cui io sappia. In caso di dubbio, e usando C99, la conversione in 'long long unsigned' è piuttosto buona; potrebbe esserci un caso per l'utilizzo di un cast su uintmax_t e PRIXMAX o equivalente.

Oppure, come FUZxxlreminded me, è possibile utilizzare il modificatore j per indicare un tipo di intero 'max'. Per esempio:

printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter); 
+2

non avrebbe saputo dire meglio. Usare (u) intmax_t e PRI (d | u) MAX (o equivalente) può essere la soluzione migliore per la maggior parte dei tipi problematici definiti dal sistema. –

+1

Sapevo già quelle macro, ma mi sembravano così brutte. Grazie per il consiglio. – kmm

+2

Sono brutti, ma sono la cosa più vicina al portatile che io conosca. –

Problemi correlati