C++ extern关键字

1、extern 修饰变量和函数

用extern修饰一个变量,其实就是告诉编译器,这个变量是要引用外部链接文件中的变量,而不是要定义一个变量。因此编译时不会给extern变量分配内存,因为编译器会给定义分配空间,而不会给声明分配空间。

2、extern "C"

extern “C” 相当于告诉编译器,这部分的变量和函数使用C语言的规则来编译(因为C++开发有时需要调用一些C语言代码)。

  1. 可以在C库的头文件中使用extern “C”:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    // all of your legacy C code here
    
    #ifdef __cplusplus
    }
    #endif
    
  2. 或者在C++代码文件里使用extern “C”

    extern "C"
    {
    	#include "cExample.h" 
    }
    

为什么要使用extern "C"

C++支持函数重载,编译函数时不仅记录函数名,还需要记录函数参数类型和数量,而C不支持函数重载,因此只需要记录函数名即可。也就是说,如果C++使用一个C语言库的函数时不加extern “C”,那么编译的时候,使用g++编译C++代码文件,使用gcc编译C代码文件,结果对于同一个函数void foo(int a),C++把它编译成_foo_int(只是简单举例,实际不是这样),C把它编译成_foo,结果会导致链接出错,因为C++找不到这个函数。而C++调用C库函数时如果使用extern "C"将其包起来,则C++编译器会按照C语言的规则来编译这个函数(即_foo),就能链接成功。

使用extern "C"的例子

假设有两个C语言的文件:c.h和c.c,前者是头文件,后者是具体的实现代码。还有一个C++程序文件main.cpp,三者内容如下:

main.cpp

#include <cassert>
#include "c.h"

int main() {
    assert(f() == 1);
}

c.h

#ifndef C_H
#define C_H

/* This ifdef allows the header to be used from both C and C++ 
 * because C does not know what this extern "C" thing is. */
#ifdef __cplusplus
extern "C" {
#endif
int f();
#ifdef __cplusplus
}
#endif

#endif

c.c

#include "c.h"
int f(void) { return 1; }

编译、链接和运行程序的命令如下:

g++ -c -o main.o -std=c++98 main.cpp
gcc -c -o c.o -std=c89 c.c
g++ -o main.out main.o c.o
./main.out

其中,使用g++编译main.cpp得到目标文件main.o,使用gcc编译c.c得到目标文件c.o,最后使用g++将main.o和c.o链接起来得到可执行文件main.out,最后运行main.out即可。其中,gcc按照C语言规则编译c.c,因此函数 f 被编译成 _f ;g++在编译main.cpp时,发现头文件中有extern “C”,因此按照C语言规则来编译,也把函数 f 编译成 _f。最终g++能够成功链接c.o和main.o。

假如头文件c.h中没有使用extern “C”,那么g++编译main.cpp时会把函数 f 编译成其他模样(叫做mangled,即被打乱了,而不是C语言那样只是简单加下划线),导致main.o和c.o中对同一个函数的表示方法不一致,最终会导致链接出错:

main.cpp:6: undefined reference to `f()'

参考Decompile a g++ generated binary to see what is going on

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值