C++中extern的作用

详见博主:http://blog.csdn.net/keensword/article/details/401114

先来介绍一下C++中的单定义规则:变量只能有一次定义。

为了满足单定义规则,C++提供两种变量声明:

一种是定义声明(defining declaration)简称定义,给变量分配内存空间;

另一种是引用声明(referencing declaration)简称声明,不给变量分配空间,因为它引用已有变量。

在全局变量中,引用声明使用extern关键字且不进行初始化,否则声明为定义,导致分配空间:

1
2
3
int x; // definition x is 0
extern int y; //y defined in elsewhere
extern char c = ‘a’; // definition, c is initialized

extern关键字的作用:

告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面没有找到相应的变量或者函数,会在当前文件的后面或者其他文件中有定义。

例子:

全局变量/函数

A.cpp

1
int i = 10;

B.cpp

1
2
3
4
int i;
void main()
{
}

在A.cpp中定义一个全局变量i,在B中也定义了一个全局变量i,编译能正常通过,但是链接的时候会报错:

原因:在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。

但是到了链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在这个时候就会出现错误,也就是上面提示的重复定义的错误。

因此,各个文件中定义的全局变量名不可相同。

如果一个文件中定义的全局变量,可以在整个程序的任何地方被使用。那么在A.cpp定义的全局变量,B.cpp可以直接使用吗?

A.cpp

1
int i = 10;

B.cpp

1
2
3
4
5
int main() {
    cout << i << endl;
 
    return 0;
}

会出现编译错误:

原因:文件中定义的全局变量的可见性扩展到整个程序是在链接完成之后,而在编译阶段,他们的可见性仍局限于各自的文件。

为了解决这个问题,引入extern关键字,使编译器能够认识在别的地方已经定义但是在本文件中还没有定义的变量:

A.cpp

1
int i = 10;

B.cpp

1
2
3
4
5
6
extern int i;
int main() {
    cout << i << endl;
 
    return 0;
}

正常输出:

 C++文件中调用C方式编译的函数

因为C++相比C添加了很多新的特性,因此两者的编译方式不一样。在多文件的程序调用中也会出现一些问题:

多文件程序中的函数调用:

A.cpp

1
2
3
4
5
6
#include <iostream>
using namespace std;
 
void func() {
    cout << "hello" << endl;
}

B.cpp

1
2
3
4
5
6
7
extern void func();
 
int main() {
    func();
 
    return 0;
}

可以正常编译链接。一般的程序大都是通过包含头文件来完成函数的声明,即在头文件中加入声明语句void func(); 并且在B.CPP中加入包含语句:#include “A.h”

不同编译方式下的函数调用:

在工程中,不仅有CPP文件,还有以C方式编译的C文件时出现的问题:

A.c

1
2
void func() {
}

B.cpp

1
2
3
4
5
6
7
8
9
10
#include<iostream>
using namespace std;
 
extern void func();
 
int main() {
    func();
 
    return 0;
}

A.CB.cpp分别编译,都没有问题,但是链接时出现错误:

原因:不同的编译方式产生的冲突

解决方法:使用extern关键字

B.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
 
extern "C"
{
    void func();
}
 
int main() {
    func();
 
    return 0;
}

相当于告诉编译器func()函数是用C方式编译的。

对于全局变量也是如此:

A.c

1
int i;

B.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
 
extern "C"
{
    int i = 100;
}
 
int main() {
    cout << i << endl;
 
    return 0;
}

可以运行通过。

A.c

1
int i = 100;

B.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
 
extern "C"
{
    extern int i;
}
 
int main() {
    cout << i << endl;
 
    return 0;
}

A.c中给i赋初值,B.cpp中的int i; 前要不要加extern?

不加会报错:

 

posted @   KYZH  阅读(693)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示