如何用printf显示off_t,nlink_t,size_t等特殊类型?
- 2024-10-28 08:37:00
- admin 原创
- 87
问题描述:
在我的程序中,我统计他们想要的文件并发送数据。统计的字段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
",
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 位系统上运行。现在使用强制转换似乎可以正常工作,但在多少个平台上可以正常工作?
解决方案 1:
没有完全可移植的方法来实现这一点,而且很麻烦。
size_t
C99为内置类型提供了一种类似%zu
符号的机制(并且还有一些额外的、类似的限定符)。
它还为<inttypes.h>
标题提供了诸如 PRIX32 之类的宏,以定义用于打印 32 位十六进制常量的正确限定符(在本例中):
printf("32-bit integer: 0x%08" PRIX32 "
", var_of_type_int32_t);
对于系统定义的类型(例如 POSIX 定义的类型),据我所知,没有好的方法来处理它们。因此,我所做的就是猜测一个“安全”的转换,然后相应地打印,包括强制转换,这就是您在问题中说明的。这令人沮丧,但据我所知没有更好的方法。如果有疑问,并且使用 C99,那么转换为“unsigned long long”就很好;可能存在使用强制转换为uintmax_t
PRIXMAX 或等效的情况。
或者,正如FUZxxl 提醒我的那样,您可以使用修饰符j
来指示“最大”整数类型。例如:
printf("Maximal integer: 0x%08jX
", (uintmax_t)var_of_type_without_format_letter);
解决方案 2:
如何用printf显示
off_t
、、等特殊类型nlink_t
?size_t
当类型具有匹配的打印说明符时,使用该
printf("Size is %zu
", object_with_type_size_t);
当类型可能缺少匹配的打印说明符,但符号已知,并且不是扩展整数类型时,转换为最宽的整数类型。
#include <inttypes.h>
printf("PID is %jd
", (intmax_t) object_with_type_pid_t);
printf("INO is %ju
", (uintmax_t) object_with_type_ino_t);
当类型可能缺少匹配的打印说明符、符号未知且不是扩展整数类型时,转换为最宽整数类型。
nlink_t
符号未指定。uintmax_t
用于可移植性。用于intmax_t
信息性。或者使用精心设计的代码。
printf("link is %ju
", (uintmax_t) object_with_type_nlink_t);
当整数类型是扩展整数类型(
off_t
即扩展有符号整数类型)时,我们的选择会变得更加棘手。我们可以像(u)intmax_t
上面那样进行转换,并可能截断该值。我们可以转换为浮点类型,并可能丢失精度。我们可以创建精心设计的代码。
printf("link is %jd
", (intmax_t) object_with_type_off_t );
// or
printf("link is %.0Lf
", (long double) object_with_type_off_t );
// or
// off_t is a signed extended integer type
#define OFF_DECIMAL_SIZE ((sizeof(off_t) * CHAR_BIT - 1)*28/93 + 3)
char buf[OFF_DECIMAL_SIZE];
printf("link is %s
", prt_off(buf, object_with_type_off_t));
支持代码
// off_t is a signed extended integer type
#define OFF_DECIMAL_STR_SIZE ((sizeof(off_t) * CHAR_BIT - 1)*28/93 + 3)
char* prt_off(char *dest, off_t off) {
char buffer[OFF_DECIMAL_STR_SIZE];
// Start filling from the end
char *p = &buffer[sizeof buffer - 1];
*p = ' ';
// Work with negative values to well handle the min value
off_t an = off < 0 ? off : -off;
do {
*(--p) = (char) ('0' - an % 10);
an /= 10;
} while (an);
if (off < 0) {
*(--p) = '-';
}
size_t size_used = &buffer[sizeof(buffer)] - p;
return memcpy(dest, p, size_used);
}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件