Как использовать printf для отображения off_t, nlink_t, size_t и других специальных типов?
-
05-07-2019 - |
Вопрос
В моей программе я оцениваю нужные файлы и отправляю данные. Поля статистики struct
являются специальными типами:
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 */
};
Ниже приведен соответствующий код для моего вопроса:
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);
Как распечатать эти типы портативным и эффективным способом? Сначала я сделал это без приведения, угадав правильные спецификаторы формата. Помимо раздражающей привычки программирования, это также означало, что мой код не будет работать на 32-битной системе. Теперь с приведениями это работает, но на скольких платформах?
Решение
Нет полностью переносимого способа сделать это, и это неприятно.
C99 предоставляет механизм для встроенных типов, таких как size_t
, с нотацией %zu
(и есть несколько дополнительных похожих классификаторов).
Он также предоставляет заголовок <inttypes.h>
с макросами, такими как PRIX32, для определения правильного квалификатора для печати 32-разрядной шестнадцатеричной константы (в данном случае):
printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t);
Для системных типов (таких как те, которые определены в POSIX), AFAIK, нет хорошего способа их обработать. Итак, что я делаю, так это на лету догадываюсь о «безопасном» преобразовании, а затем печатаю соответственно, включая состав, что вы и иллюстрируете в этом вопросе. Это расстраивает, но лучшего способа, о котором я знаю, нет. В случае сомнений и использования C99 преобразование в «unsigned long long» довольно хорошо; может быть случай использования приведений к uintmax_t
и PRIXMAX или эквивалентным.
Или как FUZxxl напомнили мне, что вы можете использовать модификатор j
для указания целочисленного типа 'max'. Например:
printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);