I am currently working on a software project in C which has to run on a variety of platforms. I try to remain as close to the C90 standard as possible, but need some commonly supported extensions like stdint.h and an unsigned long long type. I deliberately do not want to "fall back" to the C99 standard since some of the compilers that I use do not support all C99 features like mixed declarations and code etc.
我目前正在开发一个C软件项目,它必须在各种平台上运行。我尽量保持尽可能接近C90标准,但需要一些通常支持的扩展,比如stdint。h和一个无符号的长类型。我故意不希望“退回”到C99标准,因为我使用的一些编译器不支持所有C99特性,比如混合声明和代码等。
Thus, I currently compile all my code with gcc on my (64-bit Ubuntu) development machine with -Wall -Wextra -pedantic -std=gnu90
(not C90 due to my use of unsigned long long etc. as described above) to address all non-format-compliant code parts. So far, I could adapt my code to get rid of all warnings but one: I cannot find a proper (printf) format for size_t that does not yield a warning from gcc. Consider the following example code which illustrates most of the things that I tried:
因此,我现在将我所有的代码都编译在我的(64位Ubuntu)开发机器上,使用-Wall -Wextra -pedantic -std=gnu90(不是C90,因为我使用了上面描述的未签名的长时间)来处理所有不符合格式的代码部分。到目前为止,我可以修改我的代码来消除所有警告,但是我不能找到一个合适的(printf)格式,因为size_t没有得到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;
}
When compiled with -Wall -Wextra -pedantic -std=gnu90
, I get warnings for the first two lines:
当用-Wall -Wextra -pedantic -std=gnu90编译时,我得到了前两行的警告:
test.c:6:3: warning: ISO C90 does not support the ‘z’ gnu_printf length modifier [-Wformat=] test.c:7:3: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
测试。c:6:3:警告:ISO C90不支持“z”gnu_printf长度修改器[-Wformat=]测试。c:7:3:警告:format ' %u '期望类型' unsigned int '的参数,但参数2有类型' long unsigned int ' [-Wformat=]
Although I do not get a warning for the third line, this is only the case on my development system. On other systems, specifically on those where size_t is some "custom" type or not "typedef"ed as unsigned long long, there will still be a warning.
虽然我没有得到第三行的警告,但这只是我的开发系统的情况。在其他系统上,特别是在size_t是一些“自定义”类型或者不是“typedef”的时候,就会有一个警告。
I am well aware that there is no format specifier for size_t in C90, but that there is one in C99. However, I thought that setting -std=gnu90
would give me the 'z' format specifier, but that assumption turned out to be incorrect.
我很清楚C90中没有size_t的格式说明,但是C99中有一个。但是,我认为设置-std=gnu90会给我一个“z”格式的说明符,但是这个假设是不正确的。
Since I could not get rid of the warning(s), I tried to define a format specifier with some preprocessor definitions like this:
由于我无法摆脱警告(s),所以我尝试定义一个具有一些预处理器定义的格式说明符:
#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;
}
I thought that this should give me the proper format specifier, the only constraint being that size_t is unsigned (which it is on all my target platforms so far). However, that does not work either:
我认为这应该给我一个合适的格式说明符,唯一的约束是size_t是未签名的(到目前为止,它是我所有的目标平台上的)。然而,这也不起作用:
test.c:15:3: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
测试。c:15:3:警告:format ' %u '期望键入' unsigned int ',但参数2有' long unsigned int ' [-Wformat=]
Is there any way, given the constraints, to overcome this warning (or to find a more elegant solution without resorting to -std=c99
)?
考虑到约束条件,是否有办法克服这个警告(或者在不使用-std=c99的情况下找到更优雅的解决方案)?
1 个解决方案
#1
1
Would you consider a cast? Casting is normally a sign of problems, but at some point it might be simplest to just write
你会考虑演员吗?铸造通常是问题的一种表现,但在某种程度上,它可能是最简单的写作。
printf("%u", (unsigned) sizeof(int));
You could even combine the cast into a macro
您甚至可以将这些转换组合成一个宏。
#define usizeof(a) ((unsigned)sizeof(a))
printf("%u", usizeof(int));
which would make it easy enough to use.
这将使它易于使用。
#1
1
Would you consider a cast? Casting is normally a sign of problems, but at some point it might be simplest to just write
你会考虑演员吗?铸造通常是问题的一种表现,但在某种程度上,它可能是最简单的写作。
printf("%u", (unsigned) sizeof(int));
You could even combine the cast into a macro
您甚至可以将这些转换组合成一个宏。
#define usizeof(a) ((unsigned)sizeof(a))
printf("%u", usizeof(int));
which would make it easy enough to use.
这将使它易于使用。