当我为编译器课程进行语义分析时遇到了一个令人困惑的案例。
#include <stdio.h>
int a = "abcd"[2];
int main()
{
char b = "abcd"[2];
printf("%d\n%c\n", a, b);
return 0;
}
GCC说&#34;错误:初始化元素不是常数&#34;变量&#34; a&#34;。
为什么?
答案 0 :(得分:5)
C语言要求全局变量的初始值设定项为常量表达式。这背后的动机是编译器能够在编译时计算表达式并将计算出的值写入生成的目标文件中。
The C standard提供了什么是常量表达式的具体规则:
- 一种 整数常量表达式 117) 应具有整数类型,并且只能有操作数 它是整数常量,枚举常量,字符常量,
sizeof
结果为整数常量的表达式,_Alignof
表达式和浮动 作为强制转换的直接操作数的常量。将运算符转换为整数常量 expression只能将算术类型转换为整数类型,除非作为一部分 操作数sizeof
要么_Alignof
操作者- 初始值设定项中的常量表达式允许更多纬度。这样的常数 表达式应为或评估为以下之一:
醇>
- 算术常量表达式
- 一个空指针常量,
- 地址常量,或
- 完整对象类型的地址常量加上或减去整数常量 表达
如您所见,非案例包括数组访问表达式或指针取消引用。因此,"abcd"[2]
不符合标准的常量表达式。
现在标准也说:
- 实现可以接受其他形式的常量表达式。
醇>
所以它不会违反允许"abcd"[1]
作为常量表达式的标准,但也不能保证允许它。
因此,您是否在编译器中允许它取决于您。它将是标准兼容的任何一种方式(虽然允许它更多的工作,因为您需要在isConstantExpression
检查中需要另一个案例,并且您需要实际能够在编译时评估表达式,所以我不得不放弃它)。
答案 1 :(得分:0)
int a =&#34; abcd&#34; [2];
a是一个在编译时初始化的全局变量,但&#34; abcd&#34; [2]是在运行时计算的。
char b =&#34; abcd&#34; [2];
这里b是局部变量,它在&#34; abcd&#34; [2]计算后的运行时启动。