C中构成常量表达式的细节是什么?
-
28-10-2019 - |
题
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
类型的整数常量表达式,但据我所知,offsetof
的标准实现不是按标准要求是整数常量表达式。这当然是可以的,因为允许实现(根据6.6第10节)接受其他形式的常量表达式,或者将offsetof
宏实现为__builtin_offsetof
,而不是通过指针减法。但是,这种观察的本质是,如果要在需要整数常量表达式的上下文中使用offsetof
,则确实需要使用实现提供的宏,而不要自己滚动。
解决方案
根据您的阅读,1,2
不是一个常数表达式。我不知道为什么不是这样,只是我同意你所说的不是(尽管事实可能应该如此)。
6.5.2指定复合文字作为后缀运算符。所以在 通用标签
操作数为(union { uint32_t i; float f; }){ 1 }
运算符和f
运算符。它不是算术常数表达式,因为第一个参数是.
类型,但它是常数表达式。
更新:我是基于对标准的不同解释。
我以前的理由是,基因编码符合稳定表达的标准,因此是恒定表达。我仍然认为它符合常量表达式的标准(第6.6段第3款),但它不是常量表达式的任何标准类型(整数,算术或地址),因此只能由6.6段落作为常量表达式10,它允许实现定义的常量表达式。
我也一直想得到您的编辑。我要争辩说,union
的“ hack”实现是一个常量表达式,但我认为它与上面的相同:它满足常量表达式(可能是地址常量)的标准,但不是整数常量表达式,因此在6.6第10款之外无效。
其他提示
如果1,2
是一个常量表达式,则将允许这样的代码进行编译:
通用标签
我不知道这是否是真正的原因,但是我可以想象,为此(常见?)错误发出一个错误比将1,2
转换为一个常量表达式更为重要。
更新:正如R.在评论中指出的那样,自从引入VLA以来,关于的代码不再是编译器错误。