extern"C"详解

我们一般在 c++ 中使用 c 语言的库时,都会引用 c 库的头文件。例如string.hc库头文件中我们经常会看到这样的代码。

#ifdef __cplusplus
    extern "C"{
#endif

......

#ifdef __cplusplus
    }
#endif

__cplusplus 定义着 c++ 编译器的版本,如果没有定义则表示当前编译器不是 c++
上述代码的意思是如果编译代码的是 c++ 编译器,那么就将中间包含的内容以 c 语言的语法编译,为什么要这么做呢,下面我举个例子

add.h

#ifndef _ADD_H
#define _ADD_H

int add(int a, int b);

#endif // _ADD_H

add.c

int add(int a, int b)
{
    return a + b;
}

main.cpp

#include <iostream>
#include "add.h"

using namespace std;

int main(int argc, char *argv[])
{
    cout << add(3, 5) << endl;
    return 0;
}

执行编译

g++ main.cpp add.c -o main

这样的编译是没问题的,因为我们用g++编译了所有文件,都按照c++的编译规则。

那么如果add.cc库的形式或者是用gcc编译的二进制文件呢?

g++ main.cpp add.o -o main
/tmp/ccGrFT1M.o:在函数‘main’中:
main.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status

编译器告诉我说没有 add 这个函数的引用,但是在add.c里面明明定义了,为什么说没有呢。

这就要从c++c语言对函数编译时的区别说起了,c++函数编译时因为有重载的语法,为了使每个函数在编译期都能绑定到唯一的函数,会将每个函数都进行重命名,比如上面的add就会编译成_add_int_int这样的符号。
main.cpp 文件中包含了 add.h,编译时就会将 add 函数编译成 _add_int_int 然后链接,而使用gcc编译的add.o,就会将add函数只编译成_add, 所以g++在链接时就说找不到引用。

解决办法是将c头文件中加入

#ifdef __cplusplus
    extern "C"{
#endif

int add(int a, int b);

#ifdef __cplusplus
    }
#endif

这样在extern "C"{}中包裹的函数都会按照c编译器的方式去编译,只会编译出 _add 这样的函数符号,这样在链接过程中才可以正确的找到和库中对应的函数。

_add_int_int 只是一种命名方式,只要能解决重载函数的唯一性问题都可以,这就要看不同的编译器如何实现了
:可以看一下c库的头文件(stdio.h等),都有这样的代码,为了保证c++程序可以正确调用c库中的函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值