10

由于局部变量也称为自动变量,并且应该在运行时在访问函数时分配内存。

int main(){
    int a; // declaration 
    return 0;
}

int main(){
    int a[]; // compilation error, array_size missing
    return 0;
}

int main(){
    int a[2]; // declaration, but can't work without array_size, 
              // so at compile time it is checked!
    return 0;
}

我的问题是在C中声明array_size是否只是一个规则,或者在编译时为数组分配内存(仍然是局部变量)

它是如何工作的?

根据 K&R 的 C 编程,数组是一个变量。第 161 页。

4

8 回答 8

11

当您声明局部变量时,它的大小在编译时是已知的,但内存分配发生在执行时。

因此,在您的示例中,没有大小的数组显然对编译器来说是一个问题,因为它不知道要包含在汇编代码中的大小是多少。

如果你不知道数组的大小,你总是可以使用指针类型和malloc/free甚至alloca. 前两个在堆上操作,alloca实际上使用堆栈。

值得注意的例外是静态变量。它们的存储空间已经在编译/链接时分配,并且不能在运行时更改。

例子:

int main(int argc, const char *argv[])
{
    int a; // a is a sizeof(int) allocated on stack
}

int main(int argc, const char *argv[])
{
    int a[2]; // a is a sizeof(int)*2 allocated on stack
}

int main(int argc, const char *argv[])
{
    int *a; // a is a sizeof(int*) allocated on stack (pointer)
    a = alloca(sizeof(int)*4); // a points to an area with size of 4 integers
                               // data is allocated on stack
}

int main(int argc, const char *argv[])
{
    static int a; // a is allocated in data segment, keeps the value
}
于 2013-03-13T12:50:11.740 回答
2
int main(){
    int a[2];
    return 0;
}

这里,int a[2];是一个名为 的变量的定义aa是两个 的数组int

在实践中发生的是编译器发出代码以将堆栈上的空间用于 2 个相邻int对象(可能是 8 个字节,但大小int取决于实现)。这当然是假设优化器没有删除该对象,因为您从不使用它。

您得到的编译器错误int a[999999999];是由于编译器强制执行的一些硬限制,因为它知道(或无论如何假设)永远不会有足够的堆栈。

于 2013-03-13T12:49:36.530 回答
1

C 中的局部变量和自动变量之间存在区别。局部变量可以是自动的或静态的,这决定了它的内存是在堆栈上分配,还是在程序第一次执行时永久分配。

使用此代码:

int main(){
  int a[];    //compilation error, array_size missing
  return 0;
}

这是一个不完整的数组int错误是因为编译器不知道程序需要分配多少s。

于 2013-03-13T13:12:21.113 回答
0

正如评论中所述的 sgar91,在调用函数时分配了一个数组,例如您的示例中的数组,并且大小必须是确定的。如果需要动态数组,则必须在堆上分配内存。

int *values = malloc(sizeof(int) * array_count);
于 2013-03-13T12:36:28.050 回答
0

数组大小应该在编译时知道,您可以将大小直接传递给数组,也可以间接传递给数组,因为内存是在编译时决定但在运行时分配的,可变大小的数组除外。

于 2013-03-13T13:40:36.160 回答
0

当您声明一个自动变量(例如函数参数或局部变量)时,就会发生自动分配。自动变量的空间在输入包含声明的复合语句时分配,并在退出该复合语句时释放。

于 2013-03-13T12:45:26.423 回答
0

这就是 C 语言中的要点,其中数组和指针不一样。

举个例子:

int main(){
   int a[5];
   int * b = malloc(sizeof(int) * 5);

  printf("sizeof a = %d\n",sizeof a);
  printf("sizeof int[5] = %d\n",sizeof(int[5]));
  printf("sizeof b = %d\n",sizeof b);

  free(b);
  return 0;
}

这将返回:

sizeof a = 20
sizeof int[5] = 20
sizeof b = 4

变量 a 在内部声明为 int[5],它是一个整数指针,指向一个有 5 个整数空间的内存块。

于 2013-03-13T12:47:20.337 回答
0

对于局部变量,它们消耗的内存在堆栈上。这意味着它们必须具有在编译时已知的固定大小,以便在调用函数时,通过更改堆栈指针的值将所需的确切内存量添加到堆栈中。这就是数组必须有大小的原因:调用函数时堆栈上的字节数必须改变一个固定的量。

调用 malloc() 和类似的方法从堆中分配内存;在运行时以这种方式分配的内存可以是可变大小的。

于 2013-03-13T12:47:44.510 回答