【发布时间】:2019-11-13 07:19:24
【问题描述】:
我有以下 C 清单:
static const int constant = (0 | ((((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))) | ((((1 << 7) - 1) << (((0 + 8) + 8) + 3)) & ((0) << (((0 + 8) + 8) + 3))) | ((((1 << 3) - 1) << ((0 + 8) + 8)) & ((0) << ((0 + 8) + 8))) | ((((1 << 8) - 1) << 0) & ((1) << 0)));
int main(int argc, char** argv)
{
return constant;
}
当我尝试使用 GCC-9.1 使用此命令行编译它时:
gcc-9 -Werror -Wpedantic main.c
我收到此错误:
main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]
这是为什么呢?这是编译器错误吗?显然,constant 是用常量表达式初始化的。
【问题讨论】:
-
@PM77-1:这不是问题所在。问题不在于表达式
constant是否是一个常量表达式,而在于它的初始化器是否是一个常量表达式。 -
会不会是某个子表达式超出了
int的范围? (请注意,clang 不会抱怨。)可能是 gcc 错误。 -
@vaigult 我无法重现错误。
-
您有 UB 是由于左移溢出导致的,因此此示例不演示编译器错误。但是,我不确定这是否完全解释了这个问题。如果您将
(1 << 6)更改为(1 << 5),GCC 9.1 是否仍会拒绝该代码? -
@JohnBollinger:对我来说,如果我将第一个(唯一的)
(1 << 6)更改为(1 << 5),错误消息就会消失。当您将 6 更改为 5 时,该术语变为((((1 << 5) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1) << ((((0 + 8) + 8) + 3) + 7))),它避免将1向左移动 32(总共向左移动 31)。这可能是编译器的“好消息”和“糟糕消息”的混合。