¿Cómo usar printf para mostrar t, nlink t, size t y otros tipos especiales?


En mi programa, stat los archivos que quieren y enviar 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 puedo imprimir estos tipos de forma portátil y eficiente? Al principio lo hice sin moldes adivinando los especificadores de formato correctos. Aparte 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ántos plataformas?

1 answers

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 el encabezado <inttypes.h> 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 hay una buena manera de manejarlos. Por lo tanto, lo que hago es tomar una conjetura voladora en una conversión 'segura' y luego imprimir en consecuencia, incluyendo el molde, que es lo que ilustran en la pregunta. Es frustrante, pero no hay mejor manera que conozco. En caso de duda, y usando C99, entonces 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 FUZxxl recordó de mí, puede utilizar el modificador j para indicar un 'max' tipo entero. Por ejemplo:

printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);
 25
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:33:58