【发布时间】:2021-10-06 05:39:15
【问题描述】:
尝试在 C 中使用 typedef'd 变量时遇到的一个问题是弄清楚实际的原始类型是 typedef'd 时,我可以使用适当的 % 说明符尝试使用printf 打印其值。大多数时候我不得不参考gcc 产生的警告。例如,当使用stat 系统调用时,返回的结构有很多具有不同typedef'd 类型的成员,如dev_t、ino_t、mode_t 等,我通常不得不猜测是什么格式说明符可能是然后编译器警告我并纠正它:
stat_demo.c: In function ‘main’:
stat_demo.c:46:45: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘__blksize_t’ {aka ‘long int’} [-Wformat=]
46 | printf("block size for file system IO: %d\n", s->st_blksize);
| ~^ ~~~~~~~~~~~~~
| | |
| int __blksize_t {aka long int}
| %ld
这是大多数人在打印 typedef 时使用的方式吗?由于您需要知道typedef'd 的实际原语是什么,这难道不是破坏重点吗?有没有更好的方法来完全抽象实际类型?
【问题讨论】:
-
您可以为自己的域类型定义完全自定义的
printf()样式函数。然后,您可以选择具有任意语义上有意义的说明符。当然,不会神奇地适用于 other 的域类型,例如dev_t等等。 :) -
你没有显示类型。当您使用
size_t时,编译器可能会将其称为long int,但格式说明符应为%zu。如果有疑问,请转换为可用的最大整数类型并使用其说明符。 -
现在你明白了为什么在没有需要的情况下定义类型是不好的。
-
这就是所谓的“泄漏抽象”,因为类型的细节必须“泄漏”出来才能正确使用它。我发现处理它的最好方法是提供一个单独的 API,将该类型的值格式化为字符串,然后使用
%s-printf( "%s\n", fmt__blksize( s->st_blksize, buffer, sizeof buffer ) );将该 API 调用的结果传递给printf>