我想了解外部。根据其中一个最佳答案 How to correctly use the extern keyword in C
这是为了解决头文件的多个包含的问题,导致同一变量的多个副本,从而导致链接错误。
所以我通过创建以下文件来尝试它:
count.h
int count;
count.c
int count = 0;
add.h
int sum(int x, int y);
add.c
#include "count.h"
int sum(int x, int y){
count = count + 1;
return x+y;}
sub.h
int sub(int x, int y);
sub.c
#include "count.h"
int sub(int x, int y){
count = count + 1;
return x - y;
}
的main.c
#include "count.h"
#include "add.h"
#include "sub.h"
#include <stdio.h>
int main(){
printf("%d\n", count);
printf("%d\n", sub(100,1));
printf("%d\n", count);
printf("%d\n", add(100,1));
printf("%d\n", count);
}
使用输出编译并运行良好:
0
99
1
101
2
我在原始的count.h文件中使用或不使用extern获得相同的输出。那么答案中我错过了什么?
现在,我认为答案是“我只是声明多个计数副本”,因为没有标题保护,这是好的,因为多个声明都可以,而多个定义则没有。 但是如果是这样的话,我希望编译以下内容,但是因为我“重新定义计数”所以没有。
int main(){
int count;
int count;
int count = 0;
}
根据这个答案,int count算作一个定义。 In C, is it valid to declare a variable multiple times?
答案 0 :(得分:2)
第二种情况的不同之处在于您在函数中的同一范围中多次声明count
。如果你这样做了:
int count;
int count;
int count = 0;
int main(){
return 0;
}
你会没事的。这样做的原因是因为没有初始值设定项的声明是暂定定义。
的第6.9.2节2 具有没有初始化程序且没有存储类的文件范围的对象的标识符声明 说明符或存储类说明符
static
构成一个 暂定定义。如果翻译单元包含一个或多个 标识符和翻译单元的暂定定义 不包含该标识符的外部定义,然后是 行为就像翻译单元包含一个 具有复合类型的该标识符的文件范围声明 截至翻译单元的末尾,初始化程序等于0。...
4 示例1
int i1 = 1; // definition, external linkage static int i2 = 2; // definition, internal linkage extern int i3 = 3; // definition, external linkage int i4; // tentative definition, external linkage static int i5; // tentative definition, internal linkage int i1; // valid tentative definition, refers to pre vious int i2; // 6.2.2 renders undefined, linkage disagreement int i3; // valid tentative definition, refers to pre vious int i4; // valid tentative definition, refers to pre vious int i5; // 6.2.2 renders undefined, linkage disagreement extern int i1; // refers to previous, whose linkage is external extern int i2; // refers to pre vious, whose linkage is internal extern int i3; // refers to previous, whose linkage is external extern int i4; // refers to previous, whose linkage is external extern int i5; // refers to previous, whose linkage is internal
答案 1 :(得分:2)
你的
int count;
count.h
中的实际上是定义,而不仅仅是声明。这是暂定的定义,但是作为每个暂定的定义,它在每个包含上述内容的翻译单元的末尾生成了int count
的正常完整定义。
因此,通过将count.h
包含在多个翻译单元中,您在程序中生成了外部对象int count
的多个定义,这在标准C中是正式非法的。它&#34;编译并运行良好& #34;只是因为许多现代C编译器实现了编译器扩展。
根据Rationale for International Standard — Programming Languages — C(参见 6.2.2标识符的链接一节),在当天的Unix编译器使用的轻松的遗留声明/定义模型中,这曾经是好的(所谓的&#34;轻松参考/ Def&#34;模型)。然而,更正式的K&amp; R C拒绝了Unix模型并将其替换为所谓的&#34; Strict Ref / Def&#34;模型,它只允许一个定义。后来,标准化委员会决定采用严格的参考/定义&#34;模型和&#34;初始化&#34;模型,仍然只允许一个定义。然而,&#34;轻松参考/ Def&#34;在旧的Unix编译器中,许多现代编译器继续支持这个模型作为扩展。
为了使您的程序符合标准C的要求,您必须从头文件中删除int count
的定义,并将其替换为非定义声明
extern int count;
这使extern
对变量声明有用。