extern 可以置于变量或者函数前,以表示这个变量或函数别的文件中定义,提示编译器在遇到此变量或函数的时候在其他模块寻找其定义。
主要使用方式有两种:
- 如果函数的声明中带有extern,说明这个函数定义在其他文件中,这样的好处是可以取代include"**.h",在一些复杂的项目中这样使用比较方便。最好的做法是全部函数声明前添加extern.
- extern "C"支持C/C++混合编译
如果没有extern,对于 int a;和int a = 0;,即是定义也是声明
但是有了ertern以后
extern int a;//声明全局变量a,只是声明,且这个全局变量已经被声明&定义过 int a; //声明&定义全局变量a extern int a =0 ;//声明&定义全局变量a 并给初值。 int a =0;//声明&定义全局变量a,并给初值,1.1 首先来看在.h中声明并定义的问题: 导致编译冲突
#ifndef TEST1H #define TEST1H extern char g_str[] = "123456"; // 声明&定义全局变量g_str void fun1(); #endif
#include "test1.h"
void fun1() { cout << g_str << endl; }
然后test2.cpp也需要这个全局变量,就需要在源文件中include
但这样会报连接错误,这是因为你把全局变量g_str的定义放在了头文件之后,test1.cpp这个模块包含了test1.h所以定义了一次g_str,而test2.cpp也包含了test1.h所以再一次定义了g_str,这个时候连接器在连接test1和test2时发现两个g_str.
解决方法:
在test2.cpp中extern char g_str[];,而不用include
还有一个问题,如果全局变量在test1.cpp中声明&定义,那么在test2.cpp中再include也没用,这时必须在test2.cpp中extern char g_str;
给程序员的建议就是全局变量使用时,对他声明定义&初始化,这通常会在.cpp中声明和定义
另外一种做法:
#ifndef TEST1H #define TEST1H extern char g_str[]; // 声明&定义全局变量g_str void fun1(); #endif
#include "test1.h"
char g_str[] = "123456"
void fun1() { cout << g_str << endl; }
1.3 总结
- 头文件中声明并定义全局变量,当其他文件include这个文件时,会编译错误
- 实际上用到这个全局变量的地方可能很多,使用时每个文件都需要include,所以把声明和定义都放在.cpp,使用的时候extern,而不extern可能也是不错的选择。这时候可以include也不会报错.
- 但全局变量和定义都放在.h中绝对不可取.
C++为了多态,编译时会将函数名和参数联合生成一个中间函数名,例如为了支持函数重载,C++会将void foo(int x, int y)编译为_foo_int_int之类的名字,C编译后在符号库中的名字则为_foo,混合编译时二者产生差异。
我们是在main.cpp文件里包含了test.h,这些函数在main.cpp里,所以会被C++编译一个中间函数名,而test.c里面的实现会被C编译器处理,所以main就找不到test.c的函数.
这个时候就必须用extren "C"了,告诉C++编译器,请使用C语言方式编译和链接.
我们将test.h里面的东西改一下写法即可:
#ifndef _DEMO_H_
#define _DEMO_H_
#ifdef __cplusplus
extern "C" {
#endif
extern int a;
extern int b;
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
//#include "test.h" #includeint a = 10; int b = 20; int add(int l, int r) { #ifndef __cplusplus //C++ printf("这是一个c程序!n"); #endif #ifdef __cplusplus //C printf("这是一个c++程序!n"); #endif return l + r; }
#include "Demo.h" #include3.1 C++中引用C的函数变量using namespace std; void main() { int c = add(1, 2); printf("c = 1 + 2 = %d n", c); system("pause"); }
在包含头文件时添加extern "C"
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x, int y);
#endif
#include "cExample.h"
int add(int x, int y)
{
return x + y;
}
extern "C"
{
#include "cExample.h";
}
int main()
{
add(2, 3);
return 0;
}
3.2 C中引用C++的函数和变量
- 由于 C语言中不支持extern “C”
- 所以还得在C++的头文件中给函数声明加上extern "C"
- C不能直接引用声明了extern “C”的头文件
- 所以不能像3.1那样直接包含头文件,
- C.cpp中还必须将C++中定义的extern “C”函数声明为extern类型
C中不能包含
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add(int x, int y);
#endif
extern int add(int x, int y);
int main()
{
add(2, 3);
return 0;
}



