如果我在两个.c文件中的每一个中定义相同的变量而不使用" extern"会发生什么?

时间:2017-11-12 09:52:47

标签: c gcc

当我有两个.c文件时如下:

file1.c中:

int x;
//code

main.c中:

int x;
int main(){return 0;}

现在,当我编译包含这两个文件的程序时,x中考虑了两个文件中的哪一个"声明"并且在其中被视为"定义"?

或究竟发生了什么?

我知道应该避免这种情况,但我真的想知道这是如何运作的。

3 个答案:

答案 0 :(得分:2)

  

这两个文件中的哪一个被x考虑"声明"并且在其中被视为"定义"?

两者都有。其中每一个都是一个暂定的定义"。但由于它只是在文件中,所以就像你在每个文件中定义x一样。因此,您显示的两个翻译单元违反了允许的程序语义。引用n1570(C11标准草案,最接近出版物),强调我的:

6.9.2 External object definitions - Paragraph 2

  

具有文件范围的对象的标识符声明   没有初始化程序,没有存储类说明符或没有   存储类说明符静态,构成一个暂定的   定义。 如果翻译单元包含一个或多个暂定单元   标识符的定义,翻译单元包含否   该标识符的外部定义,然后行为完全正确   好像翻译单元包含一个文件范围声明   标识符,在翻译结束时使用复合类型   单位,初始化程序等于0.

6.9 External definitions - Paragraph 5

  

外部定义是外部声明,也是一个   函数的定义(内联定义除外)或   宾语。 如果使用外部链接声明的标识符   表达式(除了作为sizeof或_Alignof的操作数的一部分   运算符,其结果是整数常量),在整个某处   程序应该只有一个外部定义   标识符;否则,不得超过一个。

您不能使用示例中的任何一个变量,但这并不重要。您有两个定义,更多的是标准允许的零或一个。因此,您的程序在链接时具有未定义的行为。海湾合作委员会正在做一些不友好的事情,让你顺利建立和运行你的程序。

答案 1 :(得分:1)

来自C Standards#6.2.2p2 Linkages of identifiers

  

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

来自C Standards#6.2.2p5 Linkages of identifiers

  

如果函数的标识符声明没有存储类说明符,则确定其链接与使用存储类说明符extern声明的链接完全相同。 如果对象的标识符声明具有文件范围且没有存储类说明符,则其链接是外部的

因此,如果在 file.c 中,您有:

int x;

main.c 你也有:

int x;

x都代表同一个对象和外部链接。

来自C Standards#6.2.7.p2

  

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

由于两个文件中typex相同。因此,如果您为其中任何一个分配一些值而其他值将表示相同的值,但如果您为x分配值,则链接器可能会因{{1}的多个定义而抛出duplicate symbol错误或者你可能会得到未定义的行为。

多个外部定义是C标准中信息性附录J中引用的通用扩展。 来自C Standards#J.5.11

  

J.5.11多个外部定义

     

标识符的外部定义可能不止一个   一个对象,有或没有明确使用关键字extern;如果   定义不同意,或者不止一个被初始化,   行为未定义(6.9.2)。

在你的情况下,x的定义是一致的,所以在你明确初始化其中一个之前没有问题。

答案 2 :(得分:-1)

第一个文件,

xyz@xyz-PC:~/s_flow$ vi main.c
#include<stdio.h>
int x;// this is declaration .. same as extern int x;

int main()
{
        //linker will search definition of x in other file or below this function if you mention extern, not in same function
        printf("printing x value : %d \n",x);
        return 0;
}

第二档,

xyz@xyz-PC:~/s_flow$ vi file1.c 
int x = 100 ; // this is definition

解释我在代码里面放了注释。