繁体   English   中英

为什么“初始化器元素不是常量”不能继续工作?

[英]Why “initializer element is not a constant” is… not working anymore?

static const int a = 42;
static const int b = a;

我希望在这样的代码中出现编译错误。 初始化程序必须是常量表达式或字符串文字。 存储在具有const type qualifier的int类型的对象中的值不是常数表达式。

我使用-Wall -Wextra -pedantic ,甚至使用-ansi编译。 然后:

令人惊讶的是,以下内容:

static const char * const a = "a";
static const char * const b = a;

对于下面的片段,我认为我100%确信它不应该编译:

static const int a[] = { 1, 2, 3 };
static const int b = a[1];

,但是:

  • 它适用于gcc 8.2
  • 它在gcc低于7.4时失败,并error: initializer element is not constant
  • 它在任何版本的clang上都失败

我尝试浏览网络进行解释,这主要是导致将代码从旧的stackoverflow问题中复制出来,这些问题涉及不固定的初始化器,并找出它们现在是否可以正常工作。 我找不到gcc 8变更中的任何相关内容。

我迷路了。 它是预期的行为,并且应编译此类代码吗? 为什么/为什么不呢? 在gcc7.4和gcc8.1之间有什么变化? 这是编译器错误吗? 这是编译器扩展吗?

具有静态存储持续时间的对象的初始化程序必须由常量表达式组成。 作为@EugenSh。 在评论中观察到,“恒定表达”是一个定义的术语。 具体来说,在C2011中是6.6节的主题。 描述很简单

常量表达式可以在转换过程中而不是在运行时求值,因此可以在常量可能存在的任何位置使用它。

但是魔鬼在细节上。 常量表达式的语义细节包含针对常量表达式的特定种类和用途的特定规则。

例如,表达a不是“整数常量表达式”在任何情况下,无论其类型或const的岬a ,并且因此可以不使用其中该标准要求特定种类的恒定表达的,诸如在的位域的宽度。

尽管该标准没有给出名称,但它为初始化程序中的常量表达式提供了更为宽松的规则,这就是我们在此处考虑的情况:

该常数表达式应为以下值之一或计算为以下值之一:

  • 算术常数表达式
  • 空指针常量,
  • 地址常数,或
  • 完整对象类型加上或减去整数常量表达式的地址常量。

还定义了术语“算术常数表达式”和“地址常数”:

算术常量表达式应具有算术类型,并且仅应具有整数常量,浮点常量,枚举常量,字符常量,结果为整数常量的sizeof表达式和_Alignof表达式的操作数。 [...]

地址常数是一个空指针,一个指向左值的指针,该左值指定一个静态存储持续时间的对象,或者一个指向函数的指针。 它应使用一元&运算符或强制转换为指针类型的整数常量显式创建,或通过使用数组或函数类型的表达式隐式创建。 [...]

各种b变量的初始化器均不符合这些规则。 指定具有const限定类型的对象的左值表达式不在标准要求初始化程序需要使用的任何常量表达式的元素中。

该标准确实允许

一个实现可以接受其他形式的常量表达式。

,但这并不能覆盖其对初始化程序中出现的常量表达式的特定要求。

变量b每个给定声明都违反了出现在约束之外的标准的“必须”要求。 因此,所产生的行为是不确定的,但是该标准不需要诊断。 实现可以接受诸如GCC 8.2这样的扩展形式,并且GCC的-pedantic选项仅在标准要求的情况下才能确保诊断,其中不包括这些情况。

由于行为是不确定的,因此各种实现中观察到的行为都不是不合格的。 您不能依靠符合标准的实现来拒绝不符合标准的代码。 在某些情况下(但不是这些情况),它必须诊断出不符合项,但即使在这种情况下,也无论如何都可以成功翻译。

我迷路了。 它是预期的行为,并且应编译此类代码吗?

不,但是不能安全地期望它无法编译。

为什么/为什么不呢?

上面我解释了为什么各种代码不符合要求,因此可能被符合要求的编译器拒绝。 但另一方面,不要求合格的编译器拒绝不合格的代码。

在gcc7.4和gcc8.1之间有什么变化? 这是编译器错误吗? 这是编译器扩展吗?

海湾合作委员会显然实施了一项扩展。 我不确定这是否是故意的,但这肯定是结果。 只要行为是人们天真的期望,它看起来很自然和良性,只是从GCC(不是帮助您编写符合标准的代码)的角度来看。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM