size_t格式警告,使用gcc std = gnu90

时间:2015-04-03 12:42:01

标签: c string-formatting gcc-warning size-t

我目前正在研究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的情况下找到更优雅的解决方案)?

1 个答案:

答案 0 :(得分:1)

你会考虑演员吗?转换通常是问题的标志,但在某些时候,编写

可能是最简单的
printf("%u", (unsigned) sizeof(int));

你甚至可以将演员表组合成一个宏

#define usizeof(a) ((unsigned)sizeof(a))
printf("%u", usizeof(int));

这将使其易于使用。