2009-09-09 17 views
26

En mi programa, coloco los archivos que quieren y envío los datos. Los campos de una estadística struct son todos los tipos especiales:¿Cómo usar printf para mostrar off_t, nlink_t, size_t y otros tipos especiales?

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

El código relevante para mi pregunta sigue:

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

¿Cómo se imprime este tipo de una manera portátil y eficiente? Al principio lo hice sin moldes adivinando los especificadores de formato correctos. Además de ser un hábito de programación molesto, esto también significaba que mi código no funcionaría en un sistema de 32 bits. Ahora con los moldes parece funcionar, pero ¿en cuántas plataformas?

+0

específico para clock_t: http://stackoverflow.com/questions/1083142/what-s-the-correct-way-to-use-printf-to-print-a-clock-t –

+0

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

Respuesta

25

No hay una forma totalmente portátil de hacerlo, y es una molestia.

C99 proporciona un mecanismo para tipos incorporados como size_t con la notación %zu (y hay algunos calificadores adicionales similares).

También proporciona la cabecera <inttypes.h> con macros como PRIX32 para definir el calificador correcta para la impresión de una constante de 32 bits hexadecimal (en este caso):

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

Para los tipos definidos por el sistema (tal como aquellos definidos por POSIX), AFAIK, no hay una buena manera de manejarlos. Entonces, lo que hago es tomar una conjetura voladora sobre una conversión 'segura' y luego imprimir en consecuencia, incluido el reparto, que es lo que ilustra en la pregunta. Es frustrante, pero no hay mejor manera que yo sepa. En caso de duda, y usando C99, la conversión a 'unsigned long long' es bastante buena; podría haber un caso para usar un cast a uintmax_t y PRIXMAX o equivalente.

O, como FUZxxlreminded mí, puede usar el modificador j para indicar un tipo entero 'máximo'. Por ejemplo:

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

No podría haberlo dicho mejor. Usar (u) intmax_t y PRI (d | u) MAX (o equivalente) puede ser la mejor solución para la mayoría de los tipos definidos por el sistema. –

+1

Ya conocía esos macro pero me parecían tan feos. Gracias por el consejo. – kmm

+2

Son feos, pero son lo más parecido a portátil que conozco. –

Cuestiones relacionadas