像这样一段代码
#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-04-06 16:11:54 +08:00 via Android
怀疑是被当成 VLA ?尝试禁用 VLA ?
如果是 C++的话可以考虑用 std::integral_constant 包一层 |
3
lakehylia 2023-04-06 16:28:55 +08:00
你这个为啥还要转成 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-04-06 17:19:53 +08:00
我在 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 |
10
ysc3839 2023-04-06 19:40:50 +08:00 via Android
@wudicgi 不确定 ESP32 是否支持 C++,但是 Arduino 是支持的。建议改用 C++。
|
11
TripleLens 2023-04-07 11:23:26 +08:00
试了一下用枚举常量就没有警告,这里行为可能有点不一致
|