c中的初始化vs未初始化的全局const变量

A.s*_*lar 3 c

对不起,我不太善于解释问题.所以我直接从例子开始

请看下面的例子

const int a=10;
int *ptr;

int main(){
    ptr=&a; 
    *ptr=100;   // program crashes
    printf("%d",a);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我在上面的代码中稍作修改,如下所示

const int a; // uninitialized global variable 
Run Code Online (Sandbox Code Playgroud)

那么上面的代码工作正常.

所以我的问题是为什么编译器对uninitialize和初始化全局const变量的行为不同?

我正在使用gcc for windows(mingw).

nos*_*nos 8

您正在修改一个const对象,这只是未定义的行为 - 所以不要这样做,不要忽略编译器警告.

现在,在您的特定情况下,不同行为的实际原因是,const int a=10;10必须存储在某处.由于变量是const,链接器将它放在.rodata或可执行文件的类似只读部分.当您尝试写入只读位置时,您将遇到分段错误.

用于未初始化的情况下,const int a中,a需要被因为它是在文件范围初始化为零(或; a是全局变量).然后,链接器将变量放在.bss部分中,以及在程序启动时也初始化为零的其他数据..bss部分是可读/写的,当你尝试写入时,你没有得到段错误.

所有这些都不是你可以依赖的东西,如果你使用另一个编译器或更新/更旧版本的编译器等,这可能会随着对代码的微小修改而改变.


Rah*_*thi 5

如果您的代码没有按照C标准的要求明确执行,则会隐式初始化全局变量和静态变量.

来自doc:

const是一个类型限定符.另一种类型限定符是volatile.const的目的是宣布可能放在只读存储器中的对象,并且可能增加优化的机会.

在G ++中,您将收到第二种情况的错误,即const int a;.

6.9.2外部对象定义

语义

1如果对象的标识符声明具有文件范围和初始值设定项,则声明是标识符的外部定义.

2具有文件范围而没有初始化程序且没有存储类说明符或存储类说明符为静态的对象的标识符声明构成暂定定义.如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,那么行为就像翻译单元包含该标识符的文件范围声明一样,复合类型为翻译单元的结尾,初始化程序等于0.