我曾认为C89不支持变量长度的数组声明。然而,当我使用clang -ansi
编译时,我能够运行以下代码:
double array[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
double other_array[sizeof(array)] = { 0.0 };
这里发生了什么?这不是变长数组声明吗?
sizeof
运算符产生适合于数组维度的整数常量。例如函数调用则不行。other_array
被声明为:double other_array[sizeof(array)];
它既不会有与array[]
相同数量的元素,也不会有相同的大小(这只适用于char
数组)。如果意图是声明一个具有相同元素数量的第二个数组(无论类型如何),请使用以下内容:
double other_array[sizeof(array)/sizeof(*array)];
sizeof
运算符的结果是 常量表达式,所以它不符合可变长度数组(VLA)的要求,就像以下声明一样:int other_array[5];
也不能是可变长度数组。根据C11(N1570)§6.6/p6 常量表达式(接下来我强调):
整数常量表达式117)应具有整数类型,且只能包含整数常量、枚举常量、字符常量、
sizeof
表达式结果为整数常量、_Alignof
表达式和作为转换的立即操作数的浮点常量。
为了完整起见,sizeof
运算符并不总是产生常量表达式,尽管这仅影响C89之后的标准(在C11中,可变长度数组是可选的)。参考§6.5.3.4/p2 sizeof
和 _Alignof
运算符:
如果操作数的类型是可变长度数组类型,则对操作数进行求值;否则,不对操作数进行求值,结果是整数常量。
C11
文档,第6.7.6.2节,
针对您的情况,[...]如果大小是整数常量表达式,并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型; [...]
sizeof
是一个编译时运算符,因此它产生的值被认为是编译时常量表达式。指定大小为编译时常量表达式的数组定义不是VLA。因此,在您的代码中,int other_array[sizeof(array)]
不是VLA。
关于sizeof
运算符的结果,来自《C11》第§6.5.3.4章节(重点强调)
sizeof
运算符返回它的操作数的大小(以字节为单位),可以是表达式或类型名称的括号。[...]否则,操作数未计算,结果是整数常量。
sizeof
不是“编译时操作符”,有时不会产生常量表达式。(尽管 OP 是在问有关 C89 的问题) - M.M