当我有两个.c文件时如下:
file1.c中:
int x;
//code
main.c中:
int x;
int main(){return 0;}
现在,当我编译包含这两个文件的程序时,x中考虑了两个文件中的哪一个"声明"并且在其中被视为"定义"?
或究竟发生了什么?
我知道应该避免这种情况,但我真的想知道这是如何运作的。
答案 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
都代表同一个对象和外部链接。
引用同一对象或函数的所有声明都应具有兼容类型;否则,行为未定义。
由于两个文件中type
都x
相同。因此,如果您为其中任何一个分配一些值而其他值将表示相同的值,但如果您为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
解释我在代码里面放了注释。