为什么C和C编译器将显式初始化和默认初始化的全局变量放置在不同的段中?

我读取this great post about memory layout of C programs.它说,默认初始化的全局变量驻留在BSS segment,如果你显式地提供一个值到全局变量,那么它将驻留在data segment

我已经测试了C和C中的以下程序来检查这种行为。

#include <iostream>
// Both i and s are having static storage duration
int i;     // i will be kept in the BSS segment, default initialized variable, default value=0
int s(5);  // s will be kept in the data segment, explicitly initialized variable,
int main()
{
    std::cout<<&i<<' '<<&s;
}

输出:

0x488020 0x478004

所以,从输出,它清楚地看起来像变量i& s驻留在完全不同的段中。但是,如果我从变量S中删除初始化程序(初始值5在这个程序),然后运行程序,它给我以下输出。

输出:

0x488020 0x488024

所以,从输出它清楚地看起来像变量i和s驻留在相同(在这种情况下BSS)段。

这种行为在C中也是一样的。

#include <stdio.h>
int i;      // i will be kept in the BSS segment, default initialized variable, default value=0
int s=5;    // s will be kept in the data segment, explicitly initialized variable,
int main(void)
{
    printf("%p %p\n",(void*)&i,(void*)&s);
}

输出:

004053D0 00403004

因此,我们再次通过查看输出(意味着检查变量的地址),变量i和s都位于完全不同的段中。但是,再次,如果我从变量S中删除初始值(初始值5在这个程序中),然后运行程序,它给了我以下的输出。

输出:

004053D0 004053D4

所以,从输出它清楚地看起来像变量i和s驻留在相同(在这种情况下BSS)段。

为什么C和C编译器将显式初始化和默认初始化的全局变量放置在不同的段中?为什么有一个区别全局变量驻留在默认初始化和显式初始化变量之间?如果我没有错,C和C标准从来不谈论堆栈,堆,数据段,代码段,BSS段和所有这些是实现特定的事情。那么,C实现是否可能将显式初始化和默认初始化变量存储在同一个段中,而不是保持在不同的段中?

最佳答案
语言C或C都没有“段”的概念,并不是所有的操作系​​统都做,所以你的问题不可避免地依赖于平台和编译器。

也就是说,常见的实现将不同地处理初始化变量和未初始化变量。主要区别是未初始化(或默认0初始化)数据不必与编译模块实际保存,而是仅声明/保留供以后在运行时使用。在实际的“段”术语中,初始化的数据作为二进制的一部分保存到磁盘,而未初始化的数据不是,而是在启动时分配以满足声明的“保留”。

转载注明原文:为什么C和C编译器将显式初始化和默认初始化的全局变量放置在不同的段中? - 代码日志