我目前正在研究C中的软件项目,该项目必须在各种平台上运行。我尽量保持尽可能接近C90标准,但需要一些常用的扩展,如stdint.h和unsigned long long类型。我故意不想“退回”到C99标准,因为我使用的一些编译器不支持所有C99功能,如混合声明和代码等。
因此,我目前在我的(64位Ubuntu)开发机器上用-Wall -Wextra -pedantic -std=gnu90
编译我的所有代码(由于我使用无符号long long等而不是C90,如上所述)来解决所有非符合格式的代码部分。到目前为止,我可以调整我的代码来摆脱所有警告但只有一个:我找不到size_t的正确(printf)格式,不会产生gcc的警告。请考虑以下示例代码,该代码说明了我尝试过的大部分内容:
#include <stdint.h>
#include <stdio.h>
int main()
{
printf("%zu", sizeof(int)); /* C99 format specifier for size_t */
printf("%u", sizeof(int)); /* Treat size_t as unsigned int */
printf("%lu", sizeof(int)); /* Treat size_t as unsigned long int (only works when size_t is "typedef"ed to unsigned long int) */
return 0;
}
使用-Wall -Wextra -pedantic -std=gnu90
编译时,我会收到前两行的警告:
test.c:6:3:警告:ISO C90不支持'z'gnu_printf长度修饰符[-Wformat =] test.c:7:3:警告:格式'%u'需要类型为'unsigned int'的参数,但参数2的类型为'long unsigned int'[-Wformat =]
虽然我没有收到第三行的警告,但这只是我的开发系统的情况。在其他系统上,特别是那些size_t是某种“自定义”类型或者“typedef”为unsigned long long的系统,仍会有警告。
我很清楚C90中没有size_t的格式说明符,但C99中有一个格式说明符。但是,我认为设置-std=gnu90
会给我'z'格式说明符,但这个假设被证明是错误的。
由于我无法摆脱警告,我尝试使用一些预处理器定义来定义格式说明符,如下所示:
#include <inttypes.h>
#include <stdio.h>
#ifdef __GNUC__
#define GLUE(x, y, z) x##y##z
#define GLUE_FORMAT(prefix, size) GLUE(PRI, prefix, size)
#define UINT_FORMAT(size) GLUE_FORMAT(u, size)
#define SIZE_T_FORMAT UINT_FORMAT(__SIZEOF_SIZE_T__)
#else /* C99 fall-back */
#define SIZE_T_FORMAT "zu"
#endif
int main()
{
printf("%" SIZE_T_FORMAT, sizeof(int));
return 0;
}
我认为这应该给我正确的格式说明符,唯一的限制是size_t是无符号的(到目前为止它在我的所有目标平台上)。但是,这也不起作用:
test.c:15:3:警告:格式'%u'需要类型为'unsigned int'的参数,但参数2的类型为'long unsigned int'[-Wformat =]
在有限制的情况下,有没有办法克服这个警告(或者在不诉诸-std=c99
的情况下找到更优雅的解决方案)?
答案 0 :(得分:1)
你会考虑演员吗?转换通常是问题的标志,但在某些时候,编写
可能是最简单的printf("%u", (unsigned) sizeof(int));
你甚至可以将演员表组合成一个宏
#define usizeof(a) ((unsigned)sizeof(a))
printf("%u", usizeof(int));
这将使其易于使用。