¿Cómo utilizar printf para mostrar off_t, nlink_t, size_t y otros tipos especiales?
-
05-07-2019 - |
Pregunta
En mi programa, establezco los archivos que quieren y les envío los datos.Los campos de una estadística struct
Son todos 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 es el siguiente:
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 imprimo estos tipos de forma portátil y eficiente?Al principio lo hice sin conversiones 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 casts parece funcionar, pero ¿en cuantas plataformas?
Solución
No existe una forma totalmente portátil de hacerlo y es una molestia.
C99 proporciona un mecanismo para tipos integrados como size_t
con el %zu
notación (y hay algunos calificadores adicionales similares).
También proporciona la <inttypes.h>
encabezado con macros como PRIX32 para definir el calificador correcto para imprimir una constante hexadecimal de 32 bits (en este caso):
printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t);
Para los tipos definidos por el sistema (como los definidos por POSIX), AFAIK, no existe una buena manera de manejarlos.Entonces, lo que hago es adivinar una conversión "segura" y luego imprimir en consecuencia, incluido el elenco, que es lo que usted ilustra en la pregunta.Es frustrante, pero, que yo sepa, no existe una mejor manera.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 yeso para uintmax_t
y PRIXMAX o equivalente.
O, como FUZxxl recordado yo, puedes usar el modificador j
para indicar un tipo de entero 'máximo'.Por ejemplo:
printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);