带有 C99 的 %zu 格式说明符不起作用

%zu format specifier with C99 not working

提问人:kokopelli 提问时间:8/4/2023 最后编辑:kokopelli 更新时间:11/7/2023 访问量:142

问:

我愿意使用格式字符串中的格式说明符打印一个值,但是,我总是将“zu”作为输出,而不是变量中的实际值:size_t%zusize_t

size_t val = 10;
printf("val: %zu\n", val);  // outputs "zu", not "10"

我已经看到,对于其他面临类似问题的人,解决方法是将 C 标准设置为 C99 或更高版本。

我正在使用 CMake 构建我的项目,其中有以下行:

# Set the C standard to C11
set(CMAKE_C_STANDARD 11)

所以,我认为我很好,但不,我仍然遇到同样的问题。

我可能错过了什么吗?

我正在使用以下堆栈:

  • CMake 版本 3.22
  • 使用 arm-none-eabi-gcc 版本 10.3.1 工具链进行交叉编译
  • 编译标志:-Os -g -ffunction-sections -fdata-sections -fno-common -fmessage-length=0 -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16

为了以防万一,我还添加了编译选项。还是不行。-std=c11

C cmake C99 说明符 格式 字符串

评论

0赞 Eric Postpischil 8/4/2023
编辑问题以提供最小的可重现示例
1赞 KamilCuk 8/4/2023
哪个编译器,哪个编译器版本,哪个确切的编译器选项,什么源代码,它是如何执行的,在什么平台上,在哪个架构上,什么C标准库实现,什么printf实现?
0赞 Eugene Sh. 8/4/2023
您是否尝试在 MinGW 下使用它?不确定最近是否有任何变化,但曾经有过这个问题。stackoverflow.com/questions/68900199/......
0赞 kokopelli 8/4/2023
我已经编辑了我的问题,以提供有关我正在使用的编译工具的更多详细信息。@KamilCuk检查我编辑过的消息,我希望我已经列出了所有内容。
1赞 KamilCuk 8/7/2023
is the "nano" version enabled by default?可能是。将 cmake 排除在外。我在下面发布了如何测试它。发布输出,并用它链接的内容来剖析详细的输出。是的,您使用的 newlib 版本可能是以 nano 版本编译的。此外,还要检查随编译器一起安装的规范文件。我不知道如何不强制纳米版本。请参阅 nano.specsarm-none-eabi-gcc -v

答:

2赞 KamilCuk 8/4/2023 #1

我可能错过了什么吗?

您正在使用的 Newlib 标准 C 库实现禁用,并且在其“纳米”版本中也是如此。size_tlong longprintf

您可以使用以下方法进行测试:

$ printf "%s\n" "#include <stdio.h>" "#include <stdint.h>" 'int main() { printf("%td\n", (ptrdiff_t)1); }' | arm-none-eabi-gcc --specs=nano.specs --specs=rdimon.specs -xc -
$ ./a.out  # run with binfmt or arm-none-eabi-gdb simulator mode
td

评论

0赞 Ian Abbott 8/5/2023
我猜也会被禁用(用于打印值)?%tdptrdiff_t
1赞 KamilCuk 8/5/2023
是的。 结果为 。$ printf "%s\n" "#include <stdio.h>" "#include <stdint.h>" 'int main() { printf("%td\n", (ptrdiff_t)1); }' | arm-none-eabi-gcc --specs=nano.specs --specs=rdimon.specs -xc - && ./a.outtd
0赞 kokopelli 8/7/2023
感谢您的有用回答。正如我在上面的一条评论中提到的,不,我没有使用 newlib 的 nano 规范。但是,您的意见帮助我更好地理解了这里发生的事情。我已经使用命令在 ubuntu 上安装了 arm-none-eabi 工具链。这一切都装在一个包中,我相信它们包含的 newlib 版本缺少配置。我需要花更多的时间来了解所有配置是如何工作的,但我会尝试用它编译 newlib。sudo apt-get install arm-none-eabi-gcc--enable-newlib-io-c99-formats
1赞 chqrlie 8/5/2023 #2

目标系统上使用的 C 库不支持格式长度修饰符。要么它太旧了,不支持 C99 扩展,要么故意削弱它以保存一些(相当少的)代码量,只支持 和 。您应该将值转换为并使用:z%d%u%xsize_t(unsigned)%u

size_t val = sizeof(int);
printf("val: %u\n", (unsigned)val);  // probably outputs "val: 4"
0赞 kokopelli 8/10/2023 #3

工具链中使用的标准库 (newlib)(arm GNU 工具链 10.3.1 由 arm 提供)未启用 c99 I/O 格式支持。如果未定义,则不能用作格式说明符。您可以使用配置编译标准库以使其正常工作。_WANT_IO_C99_FORMATS%zu--enable-newlib-io-c99-formats

评论

0赞 kokopelli 11/7/2023
我最近尝试了使用最新版本的工具链 (12.2.rel1) 进行相同的操作,并且这个工具链有效。