C 为什么这个常量表达式不是常量
我有以下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] 为什么?这是一个编译器错误吗?很明显,常量已经初始化了 用一个恒定的表
静态常量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;
}