不是常量初始化元素?
Not a constant initializer element?
我在为我的编译器课程做语义分析时遇到了一个令人困惑的案例。
#include <stdio.h>
int a = "abcd"[2];
int main()
{
char b = "abcd"[2];
printf("%d\n%c\n", a, b);
return 0;
}
GCC 对变量 "a" 说 "error: initializer element is not constant"。
为什么?
int a = "abcd"[2];
a 是在编译时初始化的全局变量,但 "abcd"[2] 是在 运行 时计算的。
char b = "abcd"[2];
这里的 b 是局部变量,它在 "abcd"[2] 计算后的 运行 时间初始化。
C 语言要求全局变量的初始值设定项是常量表达式。这背后的动机是编译器能够在编译时计算表达式并将计算值写入生成的目标文件。
The C standard提供了什么是常量表达式的具体规则:
- An
integer constant expression117)
shall have integer type and shall only have operands
that are integer constants, enumeration constants, character constants,
sizeof
expressions whose results are integer constants,
_Alignof
expressions, and floating
constants that are the immediate operands of casts. Cast operators in an integer constant
expression shall only convert arithmetic types to integer types, except as part of an
operand to the
sizeof
or
_Alignof
operator
.
- More latitude is permitted for constant expressions in initializers. Such a constant
expression shall be, or evaluate to, one of the following:
- an arithmetic constant expression,
- a null pointer constant,
- an address constant, or
- an address constant for a complete object type plus or minus an integer constant
expression.
如您所见,所有情况都不包括数组访问表达式或指针取消引用。因此 "abcd"[2]
不符合标准的常量表达式。
现在标准还说:
- An implementation may accept other forms of constant expressions.
所以允许"abcd"[1]
作为常量表达式并不违反标准,但也不能保证允许。
因此是否允许在编译器中使用它取决于您。无论哪种方式,它都将符合标准(尽管允许它做更多的工作,因为您需要在 isConstantExpression
检查中使用另一个案例,并且您实际上需要能够在编译时评估表达式,所以我会禁止它).
我在为我的编译器课程做语义分析时遇到了一个令人困惑的案例。
#include <stdio.h>
int a = "abcd"[2];
int main()
{
char b = "abcd"[2];
printf("%d\n%c\n", a, b);
return 0;
}
GCC 对变量 "a" 说 "error: initializer element is not constant"。
为什么?
int a = "abcd"[2];
a 是在编译时初始化的全局变量,但 "abcd"[2] 是在 运行 时计算的。
char b = "abcd"[2];
这里的 b 是局部变量,它在 "abcd"[2] 计算后的 运行 时间初始化。
C 语言要求全局变量的初始值设定项是常量表达式。这背后的动机是编译器能够在编译时计算表达式并将计算值写入生成的目标文件。
The C standard提供了什么是常量表达式的具体规则:
- An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants,
sizeof
expressions whose results are integer constants,_Alignof
expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to thesizeof
or_Alignof
operator .- More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
- an arithmetic constant expression,
- a null pointer constant,
- an address constant, or
- an address constant for a complete object type plus or minus an integer constant expression.
如您所见,所有情况都不包括数组访问表达式或指针取消引用。因此 "abcd"[2]
不符合标准的常量表达式。
现在标准还说:
- An implementation may accept other forms of constant expressions.
所以允许"abcd"[1]
作为常量表达式并不违反标准,但也不能保证允许。
因此是否允许在编译器中使用它取决于您。无论哪种方式,它都将符合标准(尽管允许它做更多的工作,因为您需要在 isConstantExpression
检查中使用另一个案例,并且您实际上需要能够在编译时评估表达式,所以我会禁止它).