赞
踩
我们经常在代码中看到这样的声明:
#ifdef __cplusplus
extern "C" {
#endif
.........
#ifdef __cplusplus
}
#endif
其中#ifdef __cplusplus是用来判断文件是否为cpp文件,这个很好理解,那被它限定的extern “C” { }又是什么意思呢?其实这个extern “C” { }就是表达了两个含义
(1)extern表示{ }内声明的函数和变量是外部变量和函数(见注释1);
(2)“C”表示{ }内的函数都是以C语言的形式编译的,告诉编译器要以C语言形式对{}的函数进行编译(对实现文件来说)或者以C语言的形式查找函数(对引用这些函数的文件来说)。
我们知道编译器对C和C++文件定义的函数在编译时会按照一定规则来记录函数的名字,由于C++允许重载,所以编译后的函数名中一般会加上函数的参数类型用以区分不同的重载函数。而C没有这样的特性,这就造成了两种文件编译后的函数名字不同,为了防止多人协作中出现C、C++语言的不同造成的兼容问题,一般要在函数的声明处加上extern “C” { 函数声明}来限定它用C语言编写, 总之,函数的实现方式一定要和函数的查找方式一致,是C都是C,C++就都是C++,以下是几种使用情况说明:
(1)一个程序中有三个文件:main.cpp, func.h, func.cpp, func.h中用extern “C” { }限定了所有function,则在main和func.cpp中无论怎么引用func.h都可以,加不加extern “C” { }都行,func.cpp会以C形式编译
(2)main.cpp, func.h, func.cpp,三个文件都没有用extern “C” { }限定,编译运行都没有问题,因为function的编译和main都是C++形式的,main中查找function是用C++形式查找的,没有问题
(3)main.c, func.h, func.cpp, 这种情况必须在func.h中加extern “C” { }, 或者在func.cpp引用func.h的地方把func.h用extern “C” {}包起来,
extern "C" {
#include "PCMFunc.h"
}
(4)main.cpp, func.h, func.c,这种情况必须在main.cpp中引用func.h是用extern “C” {}把func.h包起来
extern "C" {
#include "PCMFunc.h"
}
最后请注意这样书写
extern "C" {
#include "PCMFunc.h"
}
不要这样写
extern "C" {#include "PCMFunc.h"}
注释1:所谓外部函数和变量也就是全局函数和变量,是在整个程序的各个文件和so库中的API都可见的函数和变量,比如在1.so中引用一个头文件,头文件声明一个外部全局函数extern void func(); 在主程序中同样引用这个头文件并在主程序的某个cpp文件中实现它,那么在运行过程中,1.so是可以找到并调用这个func()的。相反,在so中实现一个extern 函数并声明导出(用.def文件),在主程序中加载声明的头文件并引用链接这个so,在主程序中照样能调用这个extern 函数。extern变量也是这样。
注释2,在所有函数外部声明一个函数或变量后,不加关键字extern时一般默认为全局,想要声明成本地函数和变量,则必须加static关键字限定为只在本文件内可见。
关于注释2需要注意的几点:
(1)全局变量指的是其生命周期是在整个程序运行的完整周期内的,并不是指这个变量定义好了之后就在各处都可见了,它仍然需要严格遵循作用域规则。例如在main函数之后定义一个变量
int main(void)
{}
int g_num = 11;
此时想要在main中使用这个g_num是不行的,因为不在它的作用域, 需要在使用之前增加 extern int g_num;或者int g_num; 这样的声明。
(2)定义在函数之后的全局变量即使在函数内用extern声明,其作用域也并不是全局的,所以它不属于global namespac的成员,不能使用全局作用域运算符::来调用它,除非它的声明或定义在main函数之上(可以在其他函数的定义或声明之后,大家都是全局的)。
注释3:extern “C++” { }也是存在的哦
extern "C++" {
... ...
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。