Comment utiliser printf pour afficher off_t, nlink_t, size_t et d'autres types spéciaux?

StackOverflow https://stackoverflow.com/questions/1401526

  •  05-07-2019
  •  | 
  •  

Question

Dans mon programme, je récupère les fichiers qu’ils veulent et les envoie. Les champs d'une stat struct sont tous des 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 est le suivant:

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 lancer en devinant les spécificateurs de format corrects. En plus d'être une habitude de programmation agaçante, cela signifiait également que mon code ne fonctionnerait pas sur un système 32 bits. Maintenant, avec les acteurs, cela semble fonctionner, mais sur combien de plates-formes?

Était-ce utile?

La solution

Il n’existe pas de méthode totalement portable pour le faire et c’est une nuisance.

C99 fournit un mécanisme pour les types intégrés tels que size_t avec la notation %zu (et il existe quelques qualificateurs supplémentaires similaires).

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

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

Pour les types définis par le système (tels que ceux définis par POSIX), autant que je sache, il n'y a pas de bon moyen de les gérer. Donc, ce que je fais est de tenter une conversion "en toute sécurité" puis d’imprimer en conséquence, y compris le casting, ce que vous illustrez dans la question. C'est frustrant, mais il n'y a pas de meilleure façon que je sache. 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 utiliser un cast sur uintmax_t et PRIXMAX ou équivalent.

Ou, comme FUZxxl m'a rappelé , 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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top