2009-09-09 11 views
26

Dans mon programme, je state les fichiers qu'ils veulent et j'envoie les données. Les champs d'une stat struct sont tous les types spéciaux:Comment utiliser printf pour afficher off_t, nlink_t, size_t et d'autres types spéciaux?

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 */ 
}; 

Le code correspondant à ma question suivante:

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); 

Comment puis-je imprimer ces types de manière portable et efficace? Au début, je l'ai fait sans moulage en devinant les spécificateurs de format correctes. En plus d'être une habitude de programmation ennuyeuse, cela signifiait aussi que mon code ne fonctionnerait pas sur un système 32 bits. Maintenant, avec les moulages, cela semble fonctionner, mais sur combien de plates-formes?

+0

spécifique pour clock_t: http://stackoverflow.com/questions/1083142/what-s-the-correct-way-to-use-printf-to-print-a-clock-t –

+0

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

Répondre

25

Il n'y a pas de moyen entièrement portable de le faire, et c'est une nuisance. C99 fournit un mécanisme pour les types intégrés comme size_t avec la notation %zu (et il y a quelques qualificatifs supplémentaires similaires).

Il fournit également l'en-tête <inttypes.h> avec des macros telles que PRIX32 pour définir la qualification correcte pour l'impression d'une constante hexadécimale (dans ce cas) 32 bits:

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

Pour les types définis par le système (par exemple ceux définis par POSIX), AFAIK, il n'y a pas de bon moyen de les gérer. Donc, ce que je fais est de faire une supposition de vol à une conversion «sûre» et ensuite imprimer en conséquence, y compris la distribution, ce qui est ce que vous illustrez dans la question. C'est frustrant, mais il n'y a pas de meilleur moyen que je connaisse. En cas de doute, et en utilisant C99, la conversion en 'unsigned long long' est plutôt bonne; il pourrait y avoir un cas pour l'utilisation d'un casting à uintmax_t et PRIXMAX ou équivalent.

Ou, en tant que FUZxxlreminded moi, vous pouvez utiliser le modificateur j pour indiquer un type entier 'max'. Par exemple:

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

N'aurait pas pu le dire mieux. L'utilisation de (u) intmax_t et de PRI (d | u) MAX (ou équivalent) peut être la meilleure solution pour les types les plus problématiques définis par le système. –

+1

Je connaissais déjà ces macros mais elles me paraissaient si moche. Merci pour le conseil. – kmm

+2

Ils sont moche, mais ils sont la chose la plus proche de portable que je connaisse. –