C 为什么这个常量表达式不是常量

C 为什么这个常量表达式不是常量,c,gcc,C,Gcc,我有以下C清单: 静态常量int常量=(0 |)((1 我得到这个错误: main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic] main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic] 为什么?这是一个编译器错误吗?很明显,常量已经初始化了 用一个恒定的表

我有以下C清单:

静态常量int常量=(0 |)((1
我得到这个错误:

main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]
main.c:1:29: error: initializer element is not a constant expression [-Werror=pedantic]
为什么?这是一个编译器错误吗?很明显,常量已经初始化了 用一个恒定的表达式

“常量表达式”在语言标准中。我怀疑GCC正以这种方式使用它,因为该标准确实要求您的初始值设定项在这种意义上是常量表达式。当然,您的代码的评估需要在这种情况下执行

常量表达式有两种语言约束:

常量表达式不得包含赋值、增量、, 减量、函数调用或逗号运算符,除非 包含在未计算的子表达式中

每个常量表达式的计算结果应为 其类型的可表示值的范围

前者不是你的问题,后者是C实现中的一个问题,类型<代码> int <代码>有31个或更少的值位(包括大多数平台上的GCC)。

(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))

请注意,按位移位结果的类型仅由其左侧操作数的类型决定。

@PM77-1:这不是问题所在。问题不在于表达式
常量
是否为常量表达式,而在于其初始值设定项是否为常量表达式。是否有子表达式溢出了
int
?(请注意,clang没有抱怨。)可能是gcc错误。@vaigult我无法重现错误。由于左移位溢出,您有UB,因此此示例未演示编译器错误。但是,我不确定这是否完全解释了问题。如果更改
gcc 9.1是否仍然拒绝代码(1)太长了,读不下去了(1),为什么要用UB来影响编译器的输出?这是UB的一部分吗?错误消息是正确的,但是它可以通过解释为什么表达式不是常量表达式(在这种情况下,子表达式溢出)来改进。@machine_1,一般来说,“未定义的行为”适用于程序和C实现的组合。它可以在翻译(编译)时或运行时表现出来。某些未定义的行为只有在运行时才有意义——例如,如果它们取决于外部提供的数据——但情况并非如此。
(((1 << 6) - 1) << ((((0 + 8) + 8) + 3) + 7))
((1 << 6) - 1) << 26
static const unsigned int constant = (0 
    | ((((1u << 6) - 1) << ((((0 + 8) + 8) + 3) + 7)) & ((1u) << ((((0 + 8) + 8) + 3) + 7)))
    | ((((1u << 7) - 1) << (((0 + 8) + 8) + 3))       & ((0u) << (((0 + 8) + 8) + 3)))
    | ((((1u << 3) - 1) << ((0 + 8) + 8))             & ((0u) << ((0 + 8) + 8)))
    | ((((1u << 8) - 1) << 0)                         & ((1u) << 0)));

int main(void) {
    // There's a potential issue with the conversion of the return value, too, but it
    // does not affect the particular expression at issue here.
    return constant;
}