I was running the following codes compiled together as: gcc A.c B.c -o combined
我正在运行以下代码编译为:gcc A.c B.c -o combined
Program A:
#include<stdio.h>
int a=1;
int b;
int main()
{
extern int a,b;
fun();
printf("%d %d\n",a,b);
}
Program B:
int a;
int b=2;
int fun()
{
printf("%d %d\n",a,b);
return 0;
}
On running the "combined" program the output was:
在运行“组合”程序时,输出为:
1 2
1 2
Now, I've a few doubts about this one:
现在,我对这个问题有些疑惑:
-
Why isn't the output:
为什么输出不是:
0 2
1 0
-
Aren't a and b defined twice?
是不是a和b定义了两次?
Please explain these clearly, I've had a lot of problems understanding extern and few of these doubts keep coming from time to time.
请清楚地解释一下,我在了解外部时遇到了很多问题,而且很少有这些疑虑不时出现。
Thanks in Advance.
提前致谢。
4 个解决方案
#1
5
A variable may be declared many times, as long as the declarations are consistent with each other and with the definition. It may be declared in many modules, including the module where it was defined, and even many times in the same module.
只要声明彼此一致并与定义一致,就可以多次声明变量。它可以在许多模块中声明,包括定义它的模块,甚至在同一模块中多次。
An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.
外部变量也可以在函数内声明。在这种情况下,必须使用extern关键字,否则编译器会将其视为局部变量的定义,该变量具有不同的范围,生命周期和初始值。此声明仅在函数内部可见,而不是在整个函数模块中可见。
Now let me repeat again definition of extern which says "external variable is a variable DEFINED outside any function block"(Please read carefully word given in BOLD). So for the Programe A
a
have definition but b
is just declaration so extern will look for its definition of 'b' which is given in Programe B
.So print from Programe A
is 1 2
.Now lets Talk about Programe B
which have declaration for a
and definition for b
so it is priting value of a
from programe A
and value of b
from current file.
现在让我再次重复extern的定义,其中“外部变量是在任何功能块之外定义的变量”(请仔细阅读BOLD中给出的单词)。所以对于Programe A a有定义,但b只是声明,所以extern将寻找它在Programe B中给出的'b'的定义。从Programe A打印出的是1 2.现在让我们谈谈已经声明的Programe B a和b的定义因此它是来自程序A的a值和来自当前文件的b的值。
#2
3
Because the variables aren't defined twice here; they are declared twice though. The functions take the values from the definition of the variables not from the declaration of the variables.
因为变量在这里没有定义两次;他们被宣布两次。这些函数采用变量定义中的值而不是变量声明中的值。
A declaration introduces an identifier and describes its type.Through declaration we assure to the complier that this variable or function has been defined somewhere else in the program and will be provided at the time of linking. As for example the declaration is:
声明引入了一个标识符并描述了它的类型。通过声明,我们向编译器保证,该变量或函数已在程序中的其他位置定义,并将在链接时提供。例如,声明是:
extern int a;
extern int a;
A definition actually instantiates/implements this identifier. The definition is : int a=5;
OR int a;
定义实际上实例化/实现此标识符。定义是:int a = 5;或者int a;
Just read on this link for further reference.
请阅读此链接以获取进一步参考。
there is this wonderful post on * too .
*上也有这篇精彩的帖子。
extern
tells the compiler that variable is defined outside so it looks outside the function and there it finds:
extern告诉编译器变量是在外部定义的,所以它看起来在函数外部,并在那里找到:
int a=1
in program A and int b=2
in program B
程序A中的int a = 1,程序B中的int b = 2
For AUTO variables :
对于AUTO变量:
int a;//both definition and declaration
int a; //定义和声明
For further knowledge of STORAGE CLASSES you can follow this link
有关存储类的进一步了解,您可以点击此链接
int a
outside the main or any other function is declaration (i.e GLOBAL) only inside any function its called definition.
在一个外部的main或任何其他函数声明(即GLOBAL)只在其调用的任何函数内定义。
#3
3
So, I am answering my own question after a long time. Although the statement:
所以,经过很长一段时间,我正在回答我自己的问题。声明虽然:
int b;
is a decalaration andint b = 2;
is the definitionint b;是一个decalaration和int b = 2;是定义
is correct but the reason everyone is giving is not clear.
是正确的,但每个人都给出的原因尚不清楚。
Had there not been a int b = 2;
, int b;
was a definition, so what is the difference?
如果没有int b = 2;,int b;是一个定义,那有什么区别?
The difference lies in the way the linker handles multiple symbol definitions. There is a concept of weak and strong symbols.
不同之处在于链接器处理多个符号定义的方式。有一个弱而强的符号概念。
The assembler encodes this information implicitly in the symbol table of the relocatable object file. Functions and initialized global variables get strong symbols. Uninitialized global variables get weak symbols.
汇编程序隐式地在可重定位目标文件的符号表中对此信息进行编码。函数和初始化的全局变量获得强符号。未初始化的全局变量得到弱符号。
So in Program A
, int a = 1
is a strong symbol while int b;
is a weak symbol, similarly in Program B
, int b = 2
is a strong symbol and while int a
is weak.
所以在程序A中,int a = 1是一个强符号而int b;是一个弱符号,类似于程序B,int b = 2是一个强符号,而int a是弱。
Given this notion of strong and weak symbols, Unix linkers use the following rules for dealing with multiply defined symbols:
鉴于强弱符号的这一概念,Unix链接器使用以下规则来处理多重定义的符号:
- Multiple strong symbols are not allowed.
- Given a strong symbol and multiple weak symbols, choose the strong symbol.
- Given multiple weak symbols, choose any of the weak symbols.
不允许使用多个强符号。
给定一个强符号和多个弱符号,选择强符号。
给定多个弱符号,选择任何弱符号。
So, now we can argue about what is happening in the above case.
那么,现在我们可以争论上述案例中发生的事情。
- Among
int b = 2
andint b
, the former is a strong symbol while the latter is weak so b is defined with value 2. - Among
int a = 1
andint a
, a is defined as 1 (same reasoning).
在int b = 2和int b中,前者是强符号,而后者是弱符号,因此b定义为值2。
在int a = 1和int a中,a被定义为1(相同的推理)。
Hence, the output 1 2
.
因此,输出1 2。
#4
1
As far as I know: Output will be 1 2 and 1 2 because you are defining a and b as a external variables in main function.So it will try to take value from other files also. As far as 2nd question i think compiler is taking initialized values of variable and merging them because both a and b are defined as global variable in both file. Case can be different if both were defined inside function. Any suggestion or other inputs are welcome.
据我所知:输出将是1 2和1 2,因为你在主函数中定义a和b作为外部变量。因此它也会尝试从其他文件中获取值。至于第二个问题,我认为编译器正在采用变量的初始值并合并它们,因为a和b都被定义为两个文件中的全局变量。如果两者都在函数内定义,则情况可能不同。欢迎提出任何建议或其他意见。
#1
5
A variable may be declared many times, as long as the declarations are consistent with each other and with the definition. It may be declared in many modules, including the module where it was defined, and even many times in the same module.
只要声明彼此一致并与定义一致,就可以多次声明变量。它可以在许多模块中声明,包括定义它的模块,甚至在同一模块中多次。
An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.
外部变量也可以在函数内声明。在这种情况下,必须使用extern关键字,否则编译器会将其视为局部变量的定义,该变量具有不同的范围,生命周期和初始值。此声明仅在函数内部可见,而不是在整个函数模块中可见。
Now let me repeat again definition of extern which says "external variable is a variable DEFINED outside any function block"(Please read carefully word given in BOLD). So for the Programe A
a
have definition but b
is just declaration so extern will look for its definition of 'b' which is given in Programe B
.So print from Programe A
is 1 2
.Now lets Talk about Programe B
which have declaration for a
and definition for b
so it is priting value of a
from programe A
and value of b
from current file.
现在让我再次重复extern的定义,其中“外部变量是在任何功能块之外定义的变量”(请仔细阅读BOLD中给出的单词)。所以对于Programe A a有定义,但b只是声明,所以extern将寻找它在Programe B中给出的'b'的定义。从Programe A打印出的是1 2.现在让我们谈谈已经声明的Programe B a和b的定义因此它是来自程序A的a值和来自当前文件的b的值。
#2
3
Because the variables aren't defined twice here; they are declared twice though. The functions take the values from the definition of the variables not from the declaration of the variables.
因为变量在这里没有定义两次;他们被宣布两次。这些函数采用变量定义中的值而不是变量声明中的值。
A declaration introduces an identifier and describes its type.Through declaration we assure to the complier that this variable or function has been defined somewhere else in the program and will be provided at the time of linking. As for example the declaration is:
声明引入了一个标识符并描述了它的类型。通过声明,我们向编译器保证,该变量或函数已在程序中的其他位置定义,并将在链接时提供。例如,声明是:
extern int a;
extern int a;
A definition actually instantiates/implements this identifier. The definition is : int a=5;
OR int a;
定义实际上实例化/实现此标识符。定义是:int a = 5;或者int a;
Just read on this link for further reference.
请阅读此链接以获取进一步参考。
there is this wonderful post on * too .
*上也有这篇精彩的帖子。
extern
tells the compiler that variable is defined outside so it looks outside the function and there it finds:
extern告诉编译器变量是在外部定义的,所以它看起来在函数外部,并在那里找到:
int a=1
in program A and int b=2
in program B
程序A中的int a = 1,程序B中的int b = 2
For AUTO variables :
对于AUTO变量:
int a;//both definition and declaration
int a; //定义和声明
For further knowledge of STORAGE CLASSES you can follow this link
有关存储类的进一步了解,您可以点击此链接
int a
outside the main or any other function is declaration (i.e GLOBAL) only inside any function its called definition.
在一个外部的main或任何其他函数声明(即GLOBAL)只在其调用的任何函数内定义。
#3
3
So, I am answering my own question after a long time. Although the statement:
所以,经过很长一段时间,我正在回答我自己的问题。声明虽然:
int b;
is a decalaration andint b = 2;
is the definitionint b;是一个decalaration和int b = 2;是定义
is correct but the reason everyone is giving is not clear.
是正确的,但每个人都给出的原因尚不清楚。
Had there not been a int b = 2;
, int b;
was a definition, so what is the difference?
如果没有int b = 2;,int b;是一个定义,那有什么区别?
The difference lies in the way the linker handles multiple symbol definitions. There is a concept of weak and strong symbols.
不同之处在于链接器处理多个符号定义的方式。有一个弱而强的符号概念。
The assembler encodes this information implicitly in the symbol table of the relocatable object file. Functions and initialized global variables get strong symbols. Uninitialized global variables get weak symbols.
汇编程序隐式地在可重定位目标文件的符号表中对此信息进行编码。函数和初始化的全局变量获得强符号。未初始化的全局变量得到弱符号。
So in Program A
, int a = 1
is a strong symbol while int b;
is a weak symbol, similarly in Program B
, int b = 2
is a strong symbol and while int a
is weak.
所以在程序A中,int a = 1是一个强符号而int b;是一个弱符号,类似于程序B,int b = 2是一个强符号,而int a是弱。
Given this notion of strong and weak symbols, Unix linkers use the following rules for dealing with multiply defined symbols:
鉴于强弱符号的这一概念,Unix链接器使用以下规则来处理多重定义的符号:
- Multiple strong symbols are not allowed.
- Given a strong symbol and multiple weak symbols, choose the strong symbol.
- Given multiple weak symbols, choose any of the weak symbols.
不允许使用多个强符号。
给定一个强符号和多个弱符号,选择强符号。
给定多个弱符号,选择任何弱符号。
So, now we can argue about what is happening in the above case.
那么,现在我们可以争论上述案例中发生的事情。
- Among
int b = 2
andint b
, the former is a strong symbol while the latter is weak so b is defined with value 2. - Among
int a = 1
andint a
, a is defined as 1 (same reasoning).
在int b = 2和int b中,前者是强符号,而后者是弱符号,因此b定义为值2。
在int a = 1和int a中,a被定义为1(相同的推理)。
Hence, the output 1 2
.
因此,输出1 2。
#4
1
As far as I know: Output will be 1 2 and 1 2 because you are defining a and b as a external variables in main function.So it will try to take value from other files also. As far as 2nd question i think compiler is taking initialized values of variable and merging them because both a and b are defined as global variable in both file. Case can be different if both were defined inside function. Any suggestion or other inputs are welcome.
据我所知:输出将是1 2和1 2,因为你在主函数中定义a和b作为外部变量。因此它也会尝试从其他文件中获取值。至于第二个问题,我认为编译器正在采用变量的初始值并合并它们,因为a和b都被定义为两个文件中的全局变量。如果两者都在函数内定义,则情况可能不同。欢迎提出任何建议或其他意见。