什么构成C中的常量表达式的详细信息?

时间:2011-02-04 00:11:18

标签: c standards constants constant-expression

C定义了至少3个“常量表达式”级别:

  • 常数表达(不合格)
  • 算术常量表达式
  • 整数常量表达式

6.6第3段内容如下:

  

常量表达式不应包含赋值,递增,递减,函数调用,   或逗号运算符,除非它们包含在不是的子表达式中   评价。

这是否意味着1,2不是常量表达式?

第8段内容如下:

  

算术常量表达式应具有算术类型且仅具有   操作数是整数常量,浮点常量,枚举常量,字符   常量和sizeof表达式。在算术常量表达式中转换运算符   只能将算术类型转换为算术类型,除非作为操作数的一部分   sizeof运算符,其结果是整数常量。

(union { uint32_t i; float f; }){ 1 }.f中的操作数是什么?如果1是操作数,那么这可能是一个算术常量表达式,但如果{ 1 }是操作数,那么它显然不是。

编辑:另一个有趣的观察:7.17第3段要求offsetof的结果是size_t类型的整数常量表达式,但{{1}的标准实现据我所知,标准不需要是整数常量表达式。这当然是可以的,因为允许实现(在6.6第10段下)接受其他形式的常量表达式,或者将offsetof宏实现为offsetof而不是通过指针减法。但是,这种观察的本质是,如果你想在需要整数常量表达式的上下文中使用__builtin_offsetof,你真的需要使用实现提供的宏而不是你自己的。

2 个答案:

答案 0 :(得分:2)

根据您的阅读,1,2不是常量表达式。我不知道为什么不是,只是我同意你的意思不是(尽管事实上应该是这样)。

6.5.2将复合文字指定为后缀运算符。所以在

(union { uint32_t i; float f; }){ 1 }.f

操作数为(union { uint32_t i; float f; }){ 1 }f .运算符。它不是算术常量表达式,因为第一个参数是union类型,但它是一个常量表达式。

更新:我的基础是对标准的不同解释。

我之前的推理是(union { uint32_t i; float f; }){ 1 }.f符合常量表达式的标准,因此是一个常量表达式。我仍然认为它符合常量表达式的标准(6.6第3段),但它不是任何标准类型的常量表达式(整数,算术或地址),因此只能作为6.6段的常量表达式10,它允许实现定义的常量表达式。

我也想要进行编辑。我打算认为offsetof的“hack”实现是一个常量表达式,但我认为它与上面的相同:它符合常量表达式的标准(可能是地址常量)但不是整数常量表达式,因此在6.6段10之外无效。

答案 1 :(得分:0)

如果1,2是一个常量表达式,这将允许这样的代码编译:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

我不知道这是否是真正的原因,但我可以想象,为这个(常见的?)错误发出错误被认为比将1,2转换为常量表达式更重要。

UPDATE :正如R.在注释中指出的那样,自引入VLA以来,代码不再是编译器错误。