如果有多个声明可能并且只允许一个定义(ref),那么为什么下面的代码会在Turbo C ++编译器中为i
的多个声明给出错误?
int main()
{
extern int i;
int i;
printf("The value of i is %d",i);
return 0;
}
答案 0 :(得分:5)
名称要么具有链接,要么没有。具有链接的名称可以具有外部或内部链接。
"连杆"是标准如何引用翻译单元中名称的可见性("翻译单元"只是预处理后源文件的内容):
[basic.link]
(2.1) - 当名称具有外部链接时,其表示的实体可以通过其他翻译单元的范围或同一翻译单元的其他范围中的名称来引用。
(2.2) - 当名称具有内部链接时,其表示的实体可以通过同一翻译单元中其他范围的名称来引用。
(2.3) - 当一个名称有无链接时,它所代表的实体不能被其他范围的名称引用
声明的链接必须匹配,您试图将先前使用外部链接声明的变量重新声明(并定义)为没有链接的变量。
[dcl.stc]
7对某一实体的连续声明所暗示的联系应予以同意。也就是说,在给定范围内,声明相同变量名称或函数名称相同重载的每个声明都应表示相同的链接。 [...]
int main()
{
extern int i; // declare i with external linkage
int i; // define i with no linkage **ERROR**
}
正如标准所暗示的,如果声明属于不同的范围,这不是一个问题,因为它们引用了不同的名称:
int main()
{
extern int i; // declare i with external linkage
{
int i; // define i with no linkage (shadows the previous declaration)
}
}
这在全局范围内也可以正常工作,因为没有显式static
声明的(非匿名)命名空间范围内的变量和函数具有外部链接:
extern int i; // declare i with external linkage
int i; // define i with external linkage
extern int j; // declare j with external linkage
static int j; // define j with internal linkage **ERROR**
static int k; // define k with internal linkage
extern int k; // declare k with internal linkage (!!)
int main()
{
}
k
的示例有点违反直觉:如果在同一范围内不存在同名的先前声明,则使用extern
声明的名称将只有外部链接,否则链接将保持不变。这不是一个错误,除非先前声明的名称没有链接,这就是为什么你不能重新声明局部变量的原因。
您可以在cppreference上找到关联规则的快速摘要。
答案 1 :(得分:0)
@ user657267已经给出了一个很好的答案,但是,正如你对他/她的回答的评论所表明的那样,你更加困惑,你想要一个技术性较低的答案。我会试一试......
extern int i; says i is a 'global' variable defined somewhere else.
int i; says i is a 'local' variable defined in side the function.
第一个声明是声明,第二个声明是声明和定义。前一份声明说,我住在这个名为全球的世界,另一个说我住在世界名为当地的世界。即使它们来自不同的世界,因此来自不同的实体,在函数main()内部,即在本地世界的一侧,它们的相同名称会产生混淆,因此编译器会抱怨多次声明。
想象一下,你的学校有两名全名同学!一个是来自不同的州/国家。主席不会抱怨同一个人的重复参赛作品吗?