【问题标题】:When is memory allocated to local variables in C何时将内存分配给 C 中的局部变量
【发布时间】:2023-03-10 20:10:02
【问题描述】:

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

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

【问题讨论】:

  • 变量怎么可能在编译时分配?
  • @sgar91:该代码中没有任何静态数组。
  • @H2CO3 当然是编译器。我确定它会分配 plenty 的它们。哦..你的意思是在程序正在编译.. nm。 =P
  • @sgar91 这将是一个本地固定长度数组变量。
  • @linuxDeveloper 不。编译器在编译时发出指令,使程序在运行时分配内存。

标签: c variables memory-management local


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这就是 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个整数空间的内存块。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:
          int main(){
              int a[2];
              return 0;
          }
          

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

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

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

          【讨论】:

          • 感谢您的帮助。我们称之为 int a[2]={9,8,4};声明或定义。
          • @linuxDeveloper:这是对定义的无效尝试({} 列表中的项目太多)。请注意,定义声明,但它们是创建它们声明的对象的特定类型的声明。
          • 再次感谢。我可以得到一些关于这个定义的细节是声明,请提供任何链接,因为它是一个常见问题。
          【解决方案6】:

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

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

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

          【讨论】:

          • main() 之外声明的变量呢?
          • @wannik 数据段。同static
          • 感谢您的回复并提及静态,@Valeri Atamaniouk
          【解决方案7】:

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

          使用此代码:

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

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-09
              • 1970-01-01
              • 2012-08-12
              • 2019-03-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多