C 多个文件中的Extern和可能的双重定义
我正在运行以下代码,这些代码被编译为:C 多个文件中的Extern和可能的双重定义,c,output,extern,storage-class-specifier,C,Output,Extern,Storage Class Specifier,我正在运行以下代码,这些代码被编译为:gcc A.c B.c-o combined 方案A: #include<stdio.h> int a=1; int b; int main() { extern int a,b; fun(); printf("%d %d\n",a,b); } 运行“组合”程序时,输出为: 1 2 1 2 现在,我对这个有一些疑问: 为什么输出不是: 02 10 a和b不是定义了两次吗 请把这些解释清楚,我在理解extern时遇到了很多问题,很少有人会时不时
gcc A.c B.c-o combined
方案A:
#include<stdio.h>
int a=1;
int b;
int main()
{
extern int a,b;
fun();
printf("%d %d\n",a,b);
}
运行“组合”程序时,输出为:
1 2
1 2
现在,我对这个有一些疑问:
欢迎任何建议或其他输入。因为变量在这里没有定义两次;不过,它们被宣布了两次。函数从变量定义中获取值,而不是从变量声明中获取值 声明引入标识符并描述其类型。通过声明,我们向编译器保证该变量或函数已在程序的其他地方定义,并将在链接时提供。 例如,声明是:
extern-int-a代码>
定义实际上实例化/实现了该标识符。
定义是:
inta=5代码>或inta代码>
请阅读以供进一步参考
也在stackoverflow上发布
extern
告诉编译器变量是在外部定义的,因此它在函数外部查找,并在那里找到:
程序a中的int a=1
和程序b中的int b=2
对于自动变量:
inta//定义和声明
有关存储类的更多信息,您可以
int a
在main或任何其他函数之外是声明(即全局),仅在其调用定义的任何函数内部。一个变量可以多次声明,只要声明彼此一致且与定义一致。它可以在许多模块中声明,包括定义它的模块,甚至在同一模块中多次声明
外部变量也可以在函数内声明。在这种情况下,必须使用EXTN关键字,否则编译器会将其视为本地变量的定义,该变量具有不同的范围、生存期和初始值。此声明将仅在函数内部可见,而不是在整个函数模块中可见
现在,让我再次重复extern的定义,即“外部变量是在任何功能块之外定义的变量”(请仔细阅读粗体)。
因此,对于程序A
A
有定义,但b
只是声明,因此extern将查找程序b
中给出的“b”的定义。因此,从程序A
打印是12
。现在让我们谈谈程序b
,它有A
的声明,并且b
的定义,因此它是程序a
中a
的priting值和当前文件中b
的priting值。因此,我在很长时间后回答了自己的问题。尽管声明:
intb代码>是一个十分音符,且intb=2代码>是定义
这是正确的,但每个人给出的原因并不清楚
如果没有aintb=2代码>,intb代码>是一个定义,那么区别是什么
不同之处在于链接器处理多个符号定义的方式。
有弱符号和强符号的概念
汇编程序在可重定位对象文件的符号表中隐式编码此信息。函数和初始化的全局变量得到强符号。未初始化的全局变量得到弱符号
因此,在程序A
中,int A=1
是一个强符号,而int b代码>是弱符号,类似地,在程序B
中,int B=2
是强符号,而int a
是弱符号
考虑到强符号和弱符号的概念,Unix链接器使用以下规则来处理多重定义的符号:
不允许使用多个强符号
给定一个强符号和多个弱符号,选择强符号
给定多个弱符号,请选择任意弱符号
所以,现在我们可以讨论在上述情况下发生了什么
在int b=2
和int b
中,前者是强符号,而后者是弱符号,因此b用值2定义
在int a=1
和int a
中,a被定义为1(相同的推理)
因此,输出12
你试图欺骗编译器,而编译器欺骗了你。这不是欺骗编译器,而是让概念正确;是声明和定义,并且在任何函数之外生效。它也成为值为0的初始化。考虑一下:int main(){int a;//声明和定义都有……int a=5;//给出了a的多个错误定义。}你也可以对外部变量尝试同样的方法;这两种方法都声明并定义了内存分配。在任何函数之外,它还使用定义良好的值(0)而不是垃圾值初始化它。很抱歉,最近出现了电源问题。。。。您所说的可能适用于自动变量,但不适用于外部变量,请查看链接i
1 2
1 2