何时将内存分配给C中的局部变量

时间:2013-03-13 12:30:29

标签: c variables memory-management local

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

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页。

8 个答案:

答案 0 :(得分:7)

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

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

如果您不知道数组的大小,可以始终使用指针类型和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
}

答案 1 :(得分:1)

int main(){
    int a[2];
    return 0;
}

此处,int a[2];是名为a的变量的定义a是一个包含两个int的数组。

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

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

答案 2 :(得分:1)

C中的 local 自动变量之间存在差异。本地变量可能是自动静态 ,它确定是否在堆栈上分配内存,或者在程序首次执行时永久分配。

使用此代码:

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

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

答案 3 :(得分:0)

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

int *values = malloc(sizeof(int) * array_count);

答案 4 :(得分:0)

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

答案 5 :(得分: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个整数。

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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