Como usar o PrintF para exibir OFF_T, NLINK_T, SIZE_T e outros tipos especiais?
-
05-07-2019 - |
Pergunta
No meu programa, eu estatizo os arquivos que eles desejam e enviam os dados. Os campos de uma estatística struct
são todos tipos especiais:
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 */
};
O código relevante para minha pergunta segue:
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);
Como faço para imprimir esses tipos de maneira portátil e eficiente? No começo, fiz isso sem elencos, adivinhando os especificadores de formato corretos. Além de ser um hábito de programação irritante, isso também significava que meu código não funcionaria em um sistema de 32 bits. Agora, com os elencos, parece funcionar, mas em quantas plataformas?
Solução
Não há uma maneira totalmente portátil de fazê -lo, e é um incômodo.
C99 fornece um mecanismo para tipos internos como size_t
com o %zu
notação (e existem alguns qualificadores extras semelhantes).
Também fornece o <inttypes.h>
Cabeçalho com macros como o PRIX32 para definir o qualificador correto para imprimir uma constante hexadecimal de 32 bits (neste caso):
printf("32-bit integer: 0x%08" PRIX32 "\n", var_of_type_int32_t);
Para os tipos definidos pelo sistema (como os definidos por Posix), Afaik, não há uma boa maneira de lidar com eles. Então, o que faço é adivinhar uma conversão 'segura' e, em seguida, imprimir de acordo, incluindo o elenco, que é o que você ilustra na pergunta. É frustrante, mas não existe uma maneira melhor que eu conheço. Em caso de dúvida, e usando C99, a conversão para 'Longa Longa' não assinada 'é muito boa; Pode haver um caso para usar um elenco para uintmax_t
e prixmax ou equivalente.
Ou, como Fuzxxxl lembrado eu, você pode usar o modificador j
para indicar um tipo inteiro 'max'. Por exemplo:
printf("Maximal integer: 0x%08jX\n", (uintmax_t)var_of_type_without_format_letter);