以下是用两个单独的文件Test1.c和Test2.c编写的两个独立代码。我没有在任何文件中使用extern
关键字。
//Test1.c
#include <stdio.h>
int a = 1;
int main()
{
printf("test1 - a val = %d\n",a);
fn();
printf("After Return : %d",a);
}
//Test2.c
#include <stdio.h>
int a;
int fn()
{
printf("test2 - a val = %d\n",a);
a++;
}
我使用gcc:
编译了这段代码gcc Test1.c Test2.c
它会生成以下输出:
test1 - a val = 1
test2 - a val = 1
我尝试在两个代码中打印变量a
的地址。地址也一样。
现在我有以下问题:
gcc
未使用,extern
是否会自动编译和链接?显然gcc
内部就是这样,因为我正在编译这两个文件。extern
关键字的行为是依赖于编译器的吗?答案 0 :(得分:3)
此代码是未定义的行为,无需诊断。 Test1.c
和Test2.c
都定义了一个带有外部链接的对象a
,违反了C11 6.9 / 5:
如果在表达式中使用了使用外部链接声明的标识符(除了作为sizeof或_Alignof运算符的操作数的一部分,其结果是整数常量),整个程序中的某个地方应该只有一个标识符的外部定义;否则,不得超过一个。
注意:“外部定义”表示文件范围的定义。 (C11 6.9 / 4,6.9 / 5)。其他一些评论/答案将“外部定义”与“具有外部链接的对象定义”或“带有extern
关键字的定义”混淆。文件范围内的static int x = 5;
是外部定义。
正如Jonathan Leffler在评论中所提到的,这个特定的结果可能是故意的GCC扩展。从C11附件J.5.11“共同扩展”:
对象的标识符可能有多个外部定义,无论是否明确使用关键字extern;如果定义不一致,或者初始化了多个,则行为未定义。
如果gcc实现了这个扩展,那么它将解释你观察到的行为。据推测,该引文中“不止一个被初始化”不计算为暂定定义生成的隐式初始化器。