
像这样一段代码
#include <stdio.h> // 100.0 / 27.0 = 3.7037 -> (int)3 #define BUFFER_SIZE ((int)((double)100 / (double)27)) // sizeof(_buffer) = 3 unsigned char _buffer[BUFFER_SIZE]; int main(void) { printf("Hello World, sizeof(buffer) = %u\n", (unsigned int)sizeof(_buffer)); return 0; } MSVC 编译器不会报任何警告, clang 通过加 -Wno-gnu-folding-constant 参数也能消除警告。
gcc 会在 _buffer 数组定义这一行报 warning: variably modified '_buffer' at file scope, 始终没找到啥办法能让它不报这个警告,只能把表达式改成整数运算形式的。
1 wudicgi OP 以下是在在线编译器中编译的结果: gcc 12.2 // 尚未找到解决办法 https://godbolt.org/z/a7sG88ooa <source>:7:1: error: variably modified '_buffer' at file scope [-Werror] 7 | unsigned char _buffer[BUFFER_SIZE]; | ^~~~~~~~ clang 16.0.0 // 添加 -Wno-gnu-folding-constant 编译参数后警告可被去除 https://godbolt.org/z/GWEoWMsvv <source>:7:15: error: variable length array folded to constant array as an extension [-Werror,-Wgnu-folding-constant] unsigned char _buffer[BUFFER_SIZE]; ^ msvc 19.33 // 没有任何警告或错误 https://godbolt.org/z/nME5W553d |
2 ysc3839 2023 年 4 月 6 日 via Android 怀疑是被当成 VLA ?尝试禁用 VLA ? 如果是 C++的话可以考虑用 std::integral_constant 包一层 |
3 lakehylia 2023 年 4 月 6 日 你这个为啥还要转成 double 再转 int 啊,直接 #define BUFFER_SIZE (100/27) 不就行了?或者 static const int BUFFER_SIZE = 100/27; 整型的除法结果就是商啊。 |
4 wudicgi OP @ysc3839 这种情况应该也是被当成 VLA 了,我改成指定 -std=c11 -Werror=vla 参数后,提示信息变为: <source>:7:1: warning: variably modified '_buffer' at file scope 7 | unsigned char _buffer[BUFFER_SIZE]; | ^~~~~~~~ <source>:7:1: error: ISO C90 forbids array '_buffer' whose size cannot be evaluated [-Werror=vla] cc1: some warnings being treated as errors 不过查到结果是 gcc 里不能禁用 VLA 支持。 |
5 wudicgi OP @lakehylia 这里为了方便看到核心问题,就放了个最简单的表达式。 实际的表达式有好几层括号,还有 (int)(x + 0.5) 这样实现四舍五入的部分,改成整数运算的表达式看着就会非常不直观。 |
6 lakehylia 2023 年 4 月 6 日 我在 mac 上面用 clang 和 gcc 没有任何警告啊,用 cpp 文件编译的 |
7 wudicgi OP 为了防止被认为可能是 X-Y 问题,我再贴一下原始问题。 如果可以正常用浮点数运算,再转成整数作为数组大小,那么我可以使用: #define CONFIG_SLICE_COUNT_PER_SECOND ((double)((double)11025 / (double)63)) #define HALF_HANN_200MS_LENGTH ((int)(((CONFIG_SLICE_COUNT_PER_SECOND * 0.2) / 2) + 0.5)) 如果为了避开这个警告信息,全部使用整数运算,那么我需要这样写: #define CONFIG_SLICE_COUNT_PER_SECOND (11025 / 63) // 恰好能被整除 #define HALF_HANN_200MS_LENGTH ((((CONFIG_SLICE_COUNT_PER_SECOND * 2) / 10) + 1) / 2) 就非常不直观,虽然对于 200ms -> 0.2s, +0.5 实现四舍五入这些我可以再写一些宏把它包装起来, 但对于 11025 / 63 这种地方,如果不是恰好能被整除的话就还是有额外的问题,不处理会损失一些精度。 |
9 wudicgi OP @lakehylia 我开始进 godbolt.org 的时候,默认语言是 C++, 编译器选择 gcc 确实没有这个警告,把语言换成 C 之后就有了。 现在默认编译时是调用的 gcc 不是 g++, 能否改成用 g++ 编译我再看看。 因为现在问题主要在发生在编译 ESP32 固件时,它的 SDK 默认调用的是 xtensa-esp32-elf-gcc.exe |
11 TripleLens 2023 年 4 月 7 日 试了一下用枚举常量就没有警告,这里行为可能有点不一致 |