为什么不能在静态数组的大小是可变的? [重复] 为什么不能在静态数组的大小是可变的? [重复]

2019-05-14 09:43发布

可能重复:
我们可以给静态数组变量的大小

我在子文件如下定义一个数组。

static int arr[siz];

这里siz是提供给孩子文件的全局变量。 但gcc编译器产生以下错误:

<filename>: <line_num> : error : storage size of ‘arr’ isn’t constant

为什么我不能定义一个static变量大小的数组?

编辑:这似乎是唯一的一个问题static int类型。 如果我改变变量类型的arrstatic intint ,错误消失,即使数组的大小仍然依赖于一个变量siz

Answer 1:

既然你声明数组的大小不是恒定的,你有什么是一个可变长度数组(VLA)。 VLA由C99标准允许的,但它存在一些局限性。 你不能有与可变长度数组staticextern存储类说明。

你有一个VLA static存储规范,它不是由C99标准允许的。

参考:

C99标准:6.7.5.2/8

实施例4可变MODI音响版的所有声明(VM)的类型必须是在任块范围或函数原型范围。 与static或extern存储类SPECI音响ER声明数组对象不能具有可变长度阵列(VLA)的类型 。 然而,对象与静态存储类SPECI音响ER可具有VM类型中声明(即,一个指向VLA类型)。 最后,与VM类型中声明的所有identi网络ERS必须是普通identi网络ERS并不能,因此,是结构或联合的成员。

所以,如果你想有一个动态大小的数组与static存储说明你将不得不使用在堆中分配一个动态数组。

#define MAX_SIZE 256
static int* gArr;
gArr = malloc(MAX_SIZE * sizeof(int));

编辑:
要回答你的问题更新:
当您删除static从声明的关键字,从声明数组改变存储符static全局,注意标准的报价之上,它明确指出了VLAS不允许与限制staticextern存储规范。 很显然,你被允许与全球存储规范,这是你所拥有的,一旦你删除一个VLA static关键字。



Answer 2:

您分配在编译时数组,所以编译器必须知道数组的提前大小。 您必须声明siz作为一个常量表达式声明之前arr ,例如:

#define siz 5

要么

enum ESizes
{
    siz = 5
};

另外,如果你需要确定在运行时它的大小,你可以在堆上用它分配malloc

static int* arr;
arr = (int*)malloc(siz * sizeof(int))

编辑 :作为eddieantonio提到,我的回答是有效的C89。 在C99它被允许声明可变大小的阵列。



Answer 3:

您不能定义大小可变的任何阵列。 这是因为arr[siz]使编译器(!)分配为您的阵列存储(当然,编译器创建一个程序,即..,但我们不要误入细节)。 但是,变量可以在运行时(!),这意味着,编译器无法知道多少内存分配的机会来改变。

你可以做的是

static int* arr;
arr = (int*) calloc(siz,sizeof(int))

这些线导致在运行时分配存储器中的程序,因此它的确切的大小可能在运行时也进行定义。



Answer 4:

你不能声明一个static因为它的空间设置在所分配的可变大小的阵列数据段 (或bss段中未初始化的变量的情况下)。 因此,编译器需要知道在编译时的大小,如果大小不是一个常数会抱怨。

造成这种情况的根本原因是数据段大小有助于生成的可执行文件之中的尺寸,这显然是在编译时创建的,并且因此必须被固定。



文章来源: Why can't the size of a static array be made variable? [duplicate]