面试题答案
一键面试extern "C"的作用
- 代码组织方面:
- 在C++ 代码中,函数名会根据C++ 的名字修饰规则进行修饰,而C库函数遵循C语言的命名规则,没有名字修饰。
extern "C"
告知C++ 编译器,被它修饰的函数应按照C语言的命名规则处理,这样可以让C++ 代码能正确识别和调用C库函数,使代码结构更清晰,明确哪些函数是来自C库的。
- 在C++ 代码中,函数名会根据C++ 的名字修饰规则进行修饰,而C库函数遵循C语言的命名规则,没有名字修饰。
- 编译链接过程方面:
- 编译阶段,C++ 编译器看到
extern "C"
修饰的函数声明,会按C语言的方式生成目标代码,而不是C++ 风格的名字修饰后的目标代码。 - 链接阶段,链接器能够根据C语言的命名规则找到对应的C库函数的目标代码,完成链接。如果没有
extern "C"
,链接器可能找不到C库函数的入口,因为C++ 修饰后的函数名与C库函数实际的名字不匹配。
- 编译阶段,C++ 编译器看到
不同文件结构下的使用示例
- 单个源文件中调用C库函数:
假设我们有一个C库函数
add
定义在add.c
中,其声明如下:
// add.c
int add(int a, int b) {
return a + b;
}
在C++ 源文件 main.cpp
中调用这个C库函数:
// main.cpp
extern "C" {
int add(int a, int b);
}
int main() {
int result = add(3, 5);
return 0;
}
这里在 main.cpp
中通过 extern "C"
声明 add
函数,按C语言规则处理该函数,从而能正确调用。
- 多个源文件,分离声明和定义:
假设我们有一个头文件
add.h
用于声明C库函数add
,add.c
实现该函数,main.cpp
调用该函数。
// add.h
#ifndef ADD_H
#define ADD_H
// 这里为了在C和C++ 中都能使用,使用条件编译
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
// add.c
#include "add.h"
int add(int a, int b) {
return a + b;
}
// main.cpp
#include "add.h"
int main() {
int result = add(3, 5);
return 0;
}
在 add.h
中通过条件编译,当在C++ 环境下编译时,使用 extern "C"
修饰函数声明,这样在 main.cpp
包含 add.h
后,就能正确调用C库函数 add
。在C语言源文件 add.c
中包含 add.h
也不会有问题,因为条件编译在C语言环境下不会包含 extern "C"
部分。