The following snippet works fine
以下代码段正常
extern int i;
int i;
int main(){
return 0;
}
Here what I got is, 'i' is declared and then defined. Since there is only one definition so thats perfectly fine.
我得到的是,'i'被声明然后被定义。由于只有一个定义,所以完全没问题。
int main(){
extern int i;
int i;
return 0;
}
Now, the above one gives the following error
现在,上面的一个给出了以下错误
new.cpp: In function ‘int main()’:
new.cpp:5:6: error: redeclaration of ‘int i’
int i;
^
new.cpp:4:13: note: previous declaration ‘int i’
extern int i;
Whats the problem here? Here also there is single definition of 'i'.
问题出在这里?这里也有'i'的单一定义。
2 个解决方案
#1
3
To understand the difference, you need to get familiar with a concept called tentative definition in C. To quote the C standard:
要理解这种差异,您需要熟悉C中称为暂定定义的概念。引用C标准:
C11, draft, §6.9.2, External object definitions
C11,draft,§6.9.2,外部对象定义
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
具有文件范围而没有初始化程序且没有存储类说明符或存储类说明符为静态的对象的标识符声明构成暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,那么行为就像翻译单元包含该标识符的文件范围声明一样,复合类型为翻译单元的结尾,初始化程序等于0。
What you have in the first snippet is only a tentative definition for i
. You can have as many tentative definitions for an object as you want (but only one definition is allowed):
您在第一个片段中所拥有的只是i的暂定定义。您可以根据需要为对象设置尽可能多的暂定定义(但只允许一个定义):
int i; // tentative definition
int i; // tentative definition
int i; // tentative definition
int main(void) {
return 0;
}
is valid.
Here, i
has external linkage and tentatively defined. If i
is defined in somewhere in the same translation unit, then that'll be the actual definition of i
. If there's no other definition of i
is found in the translation unit, then this becomes the full definition as if it was defined like:
在这里,我有外部联系和暂定。如果我在同一个翻译单元的某个地方定义,那么那将是i的实际定义。如果在翻译单元中找不到i的其他定义,那么这将成为完整定义,就好像它被定义为:
int i = 0;
int main(void) {
return 0;
}
But the second snippet int i;
is not a tentative definition. Only objects with external linkage can be defined tentatively. In second snippet, The declaration extern int i;
says i
is defined elsewhere with external linkage. But the next line int i;
says i
is defined with no linkage (local automatic variables do not have any linkage -- this is not a tentative definition). So there's a conflict of definition for i
. Hence, the first one snippet is fine but second isn't.
但是我的第二个片段;不是暂定的定义。只能暂时定义具有外部链接的对象。在第二个片段中,声明extern int i;说我在其他地方定义了外部联系。但下一行int i;说我没有链接定义(本地自动变量没有任何链接 - 这不是一个暂定的定义)。所以i的定义存在冲突。因此,第一个片段是好的,但第二个不是。
#2
0
In the second case, there are two declarations of i
in one scope. One says "there is a variable i
defined outside this function"; the other says "there is a variable i
defined inside this function". Without a new scope, that isn't allowed.
在第二种情况下,在一个范围内有两个i声明。一个人说“我在这个函数之外定义了一个变量”;另一个说“我在这个函数中定义了一个变量”。没有新的范围,这是不允许的。
The rules are different inside and outside functions.
内部和外部功能的规则是不同的。
Note that you could use:
请注意,您可以使用:
#include <stdio.h>
int i = 21;
int main(void)
{
extern int i;
i = 37;
{
int i = 57;
printf("%d\n", i);
}
printf("%d\n", i);
return 0;
}
This compiles OK (unless you include -Wshadow
in your compilation options when using GCC or Clang), and produces 57
and 37
on the output (as pointed out by CoffeeAndCode in a comment).
这个编译好(除非你在使用GCC或Clang时在编译选项中包含-Wshadow),并在输出上产生57和37(如注释中的CoffeeAndCode所指出的)。
See also How do I use extern
to share variables between source files?
另请参阅如何使用extern在源文件之间共享变量?
#1
3
To understand the difference, you need to get familiar with a concept called tentative definition in C. To quote the C standard:
要理解这种差异,您需要熟悉C中称为暂定定义的概念。引用C标准:
C11, draft, §6.9.2, External object definitions
C11,draft,§6.9.2,外部对象定义
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
具有文件范围而没有初始化程序且没有存储类说明符或存储类说明符为静态的对象的标识符声明构成暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,那么行为就像翻译单元包含该标识符的文件范围声明一样,复合类型为翻译单元的结尾,初始化程序等于0。
What you have in the first snippet is only a tentative definition for i
. You can have as many tentative definitions for an object as you want (but only one definition is allowed):
您在第一个片段中所拥有的只是i的暂定定义。您可以根据需要为对象设置尽可能多的暂定定义(但只允许一个定义):
int i; // tentative definition
int i; // tentative definition
int i; // tentative definition
int main(void) {
return 0;
}
is valid.
Here, i
has external linkage and tentatively defined. If i
is defined in somewhere in the same translation unit, then that'll be the actual definition of i
. If there's no other definition of i
is found in the translation unit, then this becomes the full definition as if it was defined like:
在这里,我有外部联系和暂定。如果我在同一个翻译单元的某个地方定义,那么那将是i的实际定义。如果在翻译单元中找不到i的其他定义,那么这将成为完整定义,就好像它被定义为:
int i = 0;
int main(void) {
return 0;
}
But the second snippet int i;
is not a tentative definition. Only objects with external linkage can be defined tentatively. In second snippet, The declaration extern int i;
says i
is defined elsewhere with external linkage. But the next line int i;
says i
is defined with no linkage (local automatic variables do not have any linkage -- this is not a tentative definition). So there's a conflict of definition for i
. Hence, the first one snippet is fine but second isn't.
但是我的第二个片段;不是暂定的定义。只能暂时定义具有外部链接的对象。在第二个片段中,声明extern int i;说我在其他地方定义了外部联系。但下一行int i;说我没有链接定义(本地自动变量没有任何链接 - 这不是一个暂定的定义)。所以i的定义存在冲突。因此,第一个片段是好的,但第二个不是。
#2
0
In the second case, there are two declarations of i
in one scope. One says "there is a variable i
defined outside this function"; the other says "there is a variable i
defined inside this function". Without a new scope, that isn't allowed.
在第二种情况下,在一个范围内有两个i声明。一个人说“我在这个函数之外定义了一个变量”;另一个说“我在这个函数中定义了一个变量”。没有新的范围,这是不允许的。
The rules are different inside and outside functions.
内部和外部功能的规则是不同的。
Note that you could use:
请注意,您可以使用:
#include <stdio.h>
int i = 21;
int main(void)
{
extern int i;
i = 37;
{
int i = 57;
printf("%d\n", i);
}
printf("%d\n", i);
return 0;
}
This compiles OK (unless you include -Wshadow
in your compilation options when using GCC or Clang), and produces 57
and 37
on the output (as pointed out by CoffeeAndCode in a comment).
这个编译好(除非你在使用GCC或Clang时在编译选项中包含-Wshadow),并在输出上产生57和37(如注释中的CoffeeAndCode所指出的)。
See also How do I use extern
to share variables between source files?
另请参阅如何使用extern在源文件之间共享变量?