在C语言中如何声明一个具有可变长度的数组

6

我知道在C语言中定义一个可变长度的数组是不可能的,但仅仅声明一个数组呢?

#include <stdio.h>

int main ()
{
  int num = 5;
  int array[num];
  printf("%d\n",sizeof(array));
  return 0;
}

以上代码编译并打印出 20。这是否属于未定义行为?

编辑 1:

如果我写成以下方式:

  int array[num] = {0};

我会得到错误:变量大小对象可能无法初始化。

编辑2:

#include <stdio.h>

void change(int *in){
  *in = 6;
}

int main ()
{
  int num = 5;
  change(&num);
  int array[num];
  printf("%d\n",sizeof(array));
  return 0;
}

gcc test.c.

上述命令会打印出正确的值24,那么编译器是如何在编译时就知道正确的大小呢?


2
sizeof 运算符返回以 字节 为单位的大小。 - Some programmer dude
谢谢,但是这是怎么工作的呢?编译器是如何正确分配字节数的? - user13373366
2
在C99及以后的版本中,定义可变长度数组是可能的,尽管在C11中它是一个可选功能。 - Paul Hankin
如果编译器可以正确分配字节,为什么不能以同样的方式初始化它们呢? - user13373366
2
请发布您的编译命令。 - Gabriel Staples
显示剩余6条评论
1个回答

7
这段代码是干净的 C99 代码。C99 添加了对可变长度数组(VLAs)的支持。C11 将其支持变成了可选项。你的代码能够编译通过,只有 printf() 需要使用 %zu 而不是 %d 来打印从 sizeof() 返回的值。
C11 §6.5.3.4 The sizeof and _Alignof operators 中写道:

¶2 sizeof 运算符返回其操作数的大小(以字节为单位),该操作数可以是表达式或类型的括号名称。大小由操作数的类型确定。结果是一个整数。如果操作数的类型是可变长度数组类型,则计算操作数的值;否则,不计算操作数的值,结果是一个整数常量。

在你的代码中,大小在运行时计算。你可以有如下代码:
printf("Enter the array size: ");
if (scanf("%d", &n) != 1 || n <= 0 || n > 1024)
{
    fprintf(stderr, "Did not get a valid size\n");
    exit(EXIT_FAILURE);
}

int array[n];

并且在打印大小时仍然是正确的-大小在运行时计算(评估)。但这只适用于VLA。VLA可能未被初始化-标准也很清楚- §6.7.9 Initialization说:实体的类型必须是未知大小的数组或不是可变长度数组类型的完整对象类型。您不能为VLA编写初始化程序。那是一个“限制”;强制编译器抱怨滥用标准。

2
它在编译时不知道正确的大小。对于VLA,它会在运行时确定正确的大小。 - Jonathan Leffler
2
C标准规定“不可这样做”。虽然它可能会像你想的那样用零初始化数组的所有元素,但标准并不是这样工作的。标准有一定的逻辑性——它不像你想的那样灵活。我希望它能够处理指定初始化器范围的数组初始化:“int array[30] = {[12:24] = 39};”表示0..11和25..29被清零。但它并没有这样做——GCC使用“...”分隔范围的扩展,这也有其自身的问题。 - Jonathan Leffler
@Alex,如果你不想遭受Ariane 5的损失,你应该遵守标准。顺便说一下,我也是几年前从Jonathan Leffler那里学到的。 - Soner from The Ottoman Empire
2
@Alex - 是的,数组是在运行时分配的,并且其大小在运行时确定(即使在您的代码中 - 即使您使用了const int n = 5;,因为那是一个常量整数,而不是整数常量)。此外,在§6.7.9¶3中对VLA有一个总禁止初始化的规定,即“不得为VLA提供初始化程序”。 - Jonathan Leffler
1
@Alex:在C++中,是的(const将它们变成整数常量和常量整数)。但这是C语言,规则是不同的——它们是不同的语言。C++没有官方支持VLA——尽管GNU编译器集合(GCC)通过g++提供了对它们的支持,当然没有初始化。 - Jonathan Leffler
显示剩余8条评论

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