C中const的外部链接

时间:2016-10-29 18:28:14

标签: c const extern linkage

当我遇到这种奇怪的行为时,我在C 中玩extern个关键字。 我有两个文件:

file1.c中

#include<stdio.h>
int main()
{
    extern int a;
    a=10;
    printf("%d",a);
    return 0;
}

file2.c中

const int a=100;

当我一起编译这些文件时,没有错误或警告,当我运行它们时,输出变为10。我曾预料到编译器应该在行a=10;上报告错误。

此外,如果我将file2.c的内容更改为

const int a;

也就是说,如果我删除全局const变量a的初始化然后编译文件,仍然没有错误或警告,但是当我运行它们时,会出现Segmentation Fault。

为什么会出现这种现象?它是否归入未定义的行为?这是编译器还是机器依赖的?

PS:我看过很多与此问题相关的问题,但要么是针对C ++,要么只讨论extern

4 个答案:

答案 0 :(得分:1)

编译和链接是两个不同的阶段。在编译期间,单个文件正在编译为目标文件。编译器会发现file1.c和file2.c在内部是一致的。在链接阶段,链接器只会将变量a的所有出现指向同一个内存位置。这是您没有看到任何编译或链接器错误的原因。

为了避免您提到的问题,建议将extern放在头文件中,然后将该头文件包含在不同的C文件中。这样编译器可以捕获标头和C文件之间的任何不一致

以下stackoverflow还谈到链接器无法对外部变量进行类型检查。

Is there any type checking in C or C++ linkers?

  

类似地,链接器不检查全局变量的类型(以及类的静态成员等),因此如果声明extern int test;在一个翻译单元中定义浮动测试;在另一个方面,你会得到不好的结果。

答案 1 :(得分:0)

这是未定义的行为,但编译器不会警告您。怎么可能呢?它不知道如何在另一个文件中声明变量。

尝试修改声明为const的变量是未定义的行为。可以(但不是必须)将变量存储在只读存储器中。

答案 2 :(得分:0)

这是C编译器的已知行为。它是C和C ++之间的差异之一,强制执行强编译时类型检查。 尝试将值分配给const时会发生分段错误,因为链接器将const值放在只读精灵段中,写入此内存地址是运行时(分段)错误。 但是在编译期间,编译器不检查任何&#34; externs&#34;,而C链接器不测试类型。因此它通过编译/链接。

答案 3 :(得分:0)

您的程序会导致未定义的行为,无需诊断(const int a是否具有初始值设定项)。 C11中的相关文本是6.2.7 / 2:

  

引用同一对象或函数的所有声明都应具有兼容类型;否则,行为未定义。

另外6.2.2 / 2:

  

在构成整个程序的翻译单元和库的集合中,具有外部链接的特定标识符的每个声明表示相同的对象或功能。

在C中,const int a = 100;表示a具有外部链接。因此它表示与extern int a;相同的对象。但是这两个声明的类型不兼容(intconst int不兼容,请参阅6.7.2以了解&#34;兼容类型&#34;)。