在C89中,数组声明中使用sizeof()

9

我曾认为C89不支持变量长度的数组声明。然而,当我使用clang -ansi编译时,我能够运行以下代码:

double array[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
double other_array[sizeof(array)] = { 0.0 };

这里发生了什么?这不是变长数组声明吗?

1
在C89中没有可变大小的数组,因此它不能被视为可变大小的数组声明。 - M.M
3个回答

8
在 ANSI C89(也称为 ISO C90) 中,sizeof 运算符产生适合于数组维度的整数常量。例如函数调用则不行。
我想再添加一条注释,因为我认为原来的代码可能存在一个容易被忽略的问题。
如果 other_array 被声明为:
double other_array[sizeof(array)];

它既不会有与array[]相同数量的元素,也不会有相同的大小(这只适用于char数组)。如果意图是声明一个具有相同元素数量的第二个数组(无论类型如何),请使用以下内容:

double other_array[sizeof(array)/sizeof(*array)];

3
不是我给你投的反对票,但这不是问题的答案。这应该是一条评论。 - Jens Gustedt
@JensGustedt 很好。但是我试图真正理解代码的目的,看到更多的技术问题,揭示为什么有人想要另一个数组,其中每个字节的元素数量为一个双精度数组。这看起来不对,而且注释在格式方面太有限了。也许我应该再次重复技术答案,以符合答案期望。 - Jens

5
这是因为 sizeof 运算符的结果是 常量表达式,所以它不符合可变长度数组(VLA)的要求,就像以下声明一样:
int other_array[5];

也不能是可变长度数组。根据C11(N1570)§6.6/p6 常量表达式(接下来我强调):

整数常量表达式117)应具有整数类型,且只能包含整数常量、枚举常量、字符常量、sizeof表达式结果为整数常量_Alignof表达式和作为转换的立即操作数的浮点常量。

为了完整起见,sizeof运算符并不总是产生常量表达式,尽管这仅影响C89之后的标准(在C11中,可变长度数组是可选的)。参考§6.5.3.4/p2 sizeof_Alignof 运算符

如果操作数的类型是可变长度数组类型,则对操作数进行求值;否则,不对操作数进行求值,结果是整数常量


3
首先,让我们看一下数组不是VLA的标准(不是)。C11文档,第6.7.6.2节,

[...]如果大小是整数常量表达式,并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型; [...]

针对您的情况,sizeof是一个编译时运算符,因此它产生的值被认为是编译时常量表达式。指定大小为编译时常量表达式的数组定义不是VLA。因此,在您的代码中,
int other_array[sizeof(array)]

不是VLA。

关于sizeof运算符的结果,来自《C11》第§6.5.3.4章节(重点强调

sizeof运算符返回它的操作数的大小(以字节为单位),可以是表达式或类型名称的括号。[...]否则,操作数未计算,结果是整数常量。


2
在 C11 中,sizeof 不是“编译时操作符”,有时不会产生常量表达式。(尽管 OP 是在问有关 C89 的问题) - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接