#ifdef __cplusplus
extern "C" {
#endif
extern double reciprocal (int i);
#ifdef __cplusplus
}
#endif
看到了如上一段代码(《Advance Linux Programming》 代码列表1.3),从以下几个方面解读一下:
- #ifdef __cplusplus/ #endif
- extern 关键字
- extern "C"
1.#ifdef / #endif
#ifdef xxx 相当于#if defined(xxx),用于条件编译,若xxx已经被宏定义,那么编译包括其后的各行,直到遇到#endif,#elif,#else语句为止。
__cplusplus是C++的自定义宏,如果定义了这个宏说明这是一段C++代码。
以上代码的意思就是如果这是一个cpp文件,那么编译器就执行extern "C"{}语句。
另外在C/C++中常用#ifndef xxx/#endif来避免重复的定义,#ifndef xxx相当于#if !defined(xxx)。
2.extern关键字
extern用来声明变量,该关键字告诉编译器,其声明的变量和函数可以在本模块使用。
用extern时仅仅声明变量而不分配内存空间。在一个项目中函数,变量等在所有源文件中必须保持一致,除非指定定义为局部的,全局变量在所有模块中只能定义一次,可以声明多次,但声明类型必须保持一致。
注:C语言中的定义和声明:
声明:
extern int x;
extern int g(int);
int f(int, int);
声明只指定标识符,不分配空间。
函数的声明可以省略extern关键字,但加上extern关键字可以知道该函数可能在其他模块定义过。
定义:
int x;
int g(int x, int y){ return x + y;}
定义是对声明的实现或实例化。
3.extern "C"
C和C++编译的区别:C++为了支持函数重载,在将代码编译到二进制文件后,函数fun(int)的函数名其实已经变成了类似fun_int这种形式,这时调用fun()函数如fun(2)就对应fun_int(2),而在C语言中是没有重载的,这样C文件在和C++混合编译的时候就会报连接错误。
"C"表示了一种编译和连接的规约,extern "C"则给代码指定了这种规约,而且不影响语义。函数声明中声明指定了extern "C",仍要遵守C++的语法规则,如类型检测参数转换等。
如果有多句代码需要加上extern "C",可以将它们放到extern "C" {}中。
《Advanced Linux Programming》中第一节的示例就用了extern "C"实现了在C语言中调用C++函数:
代码列表 1.1 ( main.c ) C源码—— main.c
#include <stdlib.h>
#include <stdio.h>
#include “reciprocal.hpp”
int main (int argc, char **argv) {
int i;
i = atoi (argv[1]);
printf (“The reciprocal of %d is %g\n”, i, reciprocal (i));
return 0;
}
代码列表 1.2 ( reciprocal.cpp ) C++ 源码—— reciprocal.cpp
#include <cassert>
#include “reciprocal.hpp”
double reciprocal (int i) {
// i 不能为 0
assert (i != 0);
return 1.0/i;
}
代码列表 1.3 ( reciprocal.hpp )包含文件—— reciprocal.hpp
#ifdef __cplusplus
extern "C" {
#endif
extern double reciprocal (int i);
#ifdef __cplusplus
}
#endif