我在网上搜索了这个问题,但是找到的信息互相矛盾。
请不要阅读随机博客之类的东西,它们通常有错误的信息。在Stack Overflow上,错误的信息往往会被downvote或者至少会有评论指出其不准确和谬误。
在上面的程序中,arr和x都在main函数内部局部声明。我认为这意味着它们都会在函数堆栈上分配空间。
C标准没有指定如何为对象分配内存。它只指定对象具有存储期,定义了变量对象的生命周期。
静态对象将从程序开始一直存在到结束;
自动对象将在包含声明(或复合文字)的最内层块{...}的生存期内存在,直到块结束;
线程本地对象将拥有线程的寿命;
分配的对象将从malloc/calloc/realloc/aligned_alloc到相应的free/realloc。
注:原文中的“variables”被划去,我猜测是因为译者想用更加准确的“objects”代替。
除此之外,C标准规定对象在其生命周期内将会:
- 为其保留内存
- 拥有一个恒定的地址(可通过使用 & 运算符观察)
现在,除此之外,还有所谓的“as-if”规则,它表示编译器可以生成任何程序代码,只要程序的外部行为相同,外部行为包括输入、输出、访问易失性对象等。
您程序中的变量具有自动存储期,这意味着每次进入主函数时,您将拥有具有新生命周期的新对象,直到主函数结束。通常,这意味着它们将存储在堆栈上,因为它将以最小的开销处理分配和释放。但是您的程序与其外部行为相同。
#include <stdio.h>
int main(void) {
printf("Hello World!");
}
这意味着编译器可以完全消除这两个变量,并且不为其保留任何空间。
现在,如果您打印这些变量的
地址:
#include <stdio.h>
int main(void) {
int arr[4] = {1,2,3,4};
int x = 10;
printf("Hello World! %p, %p\n", (void *)arr, (void *)&x);
}
因为变量的地址被使用并用于输出,C语言无法将它们优化掉。它们现在是否在堆栈上?好吧,C标准没有说明。它们需要从
main
函数开始至少具有生命周期直到结束 - 但是C编译器可以决定
不在堆栈上使用它们,因为该程序的外部行为将保持不变。
#include <stdio.h>
static int arr[4] = {1,2,3,4};
static int x = 10;
int main(void) {
printf("Hello World! %p, %p\n", (void *)arr, (void *)&x);
}
这将把这些变量放在静态数据段中;当然地址会不同,但是C语言并不保证特定对象在内存中的位置,只保证它们有地址。
{1,2,3,4}
将存储在程序映像的数据部分中。在运行时,如果您的程序甚至创建了数组变量(因为正如其他人所说,优化器可以删除没有影响的任何内容),它将在堆栈上为数组创建空间,然后将初始化程序复制到其中。或者,如果使用优化器,它可能会删除初始化程序并替换为内联寄存器设置指令。 - Zan Lynx