2009-09-09 2 views
26

In meinem Programm, state ich die Dateien, die sie wollen und senden Sie die Daten über. Die Felder eines Stat struct sind alle Sondertypen:Wie printf verwendet wird, um off_t, nlink_t, size_t und andere Sondertypen anzuzeigen?

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

Der entsprechende Code für meine Frage folgt:

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

Wie drucke ich diese Art in einer tragbaren und effizienten Art und Weise? Zuerst habe ich es ohne Abgüsse gemacht, indem ich die korrekten Formatbezeichner erraten habe. Abgesehen davon, dass es eine lästige Programmiergewohnheit war, bedeutete dies auch, dass mein Code nicht auf einem 32-Bit-System funktionieren würde. Nun scheint es bei den Casts zu funktionieren, aber auf wie vielen Plattformen?

+0

Spezifisch für clock_t: http://stackoverflow.com/questions/1083142/what-s-the-correct-way-to-use-printf-to-print-a-clock-t –

+0

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

Antwort

25

Es gibt keine vollständig portable Möglichkeit, dies zu tun, und es ist ein Ärgernis.

C99 bietet einen Mechanismus für integrierte Typen wie size_t mit der %zu Schreibweise (und es gibt einige zusätzliche, ähnliche Qualifier).

Es bietet auch die <inttypes.h> Header mit Makros wie PRIX32 die richtige Qualifier zu definieren für den Druck eines 32-Bit-Hexadezimal-Konstante (in diesem Fall):

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

Für die systemdefinierte Typen (wie die von POSIX definierten), AFAIK, gibt es keinen guten Weg, mit ihnen umzugehen. Also, was ich mache, ist eine fliegende Vermutung für eine "sichere" Konvertierung und dann entsprechend drucken, einschließlich der Besetzung, was ist, was Sie in der Frage veranschaulichen. Es ist frustrierend, aber es gibt keinen besseren Weg, von dem ich weiß. Im Zweifelsfall und mit C99 ist die Konvertierung in 'unsigned long long' ziemlich gut; Es könnte ein Fall für die Verwendung eines Cast zu uintmax_t und PRIXMAX oder gleichwertig sein.

Oder, wie FUZxxlreminded ich, können Sie den Modifikator j verwenden, um einen 'max' Integer-Typ anzuzeigen. Zum Beispiel:

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

Konnte es nicht besser gesagt haben. Die Verwendung von (u) intmax_t und PRI (d | u) MAX (oder gleichwertig) kann die beste Lösung für die meisten problematischen systemdefinierten Typen sein. –

+1

Ich kannte diese Makros schon, aber sie sahen so hässlich aus. Danke für den Hinweis. – kmm

+2

Sie sind hässlich, aber sie sind der nächsten Sache, die ich kenne. –

Verwandte Themen