extern “C“的作用

写作背景

extern "C"的作用,网上有很多文章描述。但是我在真正弄懂它的意思之前,看了2~3篇文章,依然云里雾里,感觉是那么个意思,但是没有真正通透。所以我停下来,自己在脑海里总结大家所说的,才有所领悟。
重点看【实际中是如何发挥作用的】

extern "C"的目的

extern "C"包含两部分,extern和后面的“C”,extern的作用就是申明当前修饰的变量或者函数是在其他模块(文件)中定义的,只起一个申明(说明)的作用,不分配及占用内存。
后面的"C"才是真正不好理解的。extern "C"的真实目的,是为了实现c和c++的混合编程

为何需要extern “C”

本质原因是c和c++的编译方式不一样导致的。同样是int add(int, int)函数,c++为了实现函数重载,函数名在编译后,会包含函数名和参数_add_int_int,而c中函数在编译后,只有函数名_add。所以在c++中调用c函数的时候,需要在函数申明中加上extern “C”,以告诉c++编译器,当前函数在链接找函数实现的时候,按照c的函数形式找,而不要按照c++的形式找。

使用extern "C"的场景

1、C++代码调用C语言代码
2、在C++的头文件中使用
3、在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到

extern "C"的使用形式

  • 可以在函数申明中单独使用,例如只在cpp文件开头申明外部的c函数的时候;
  • 可以用{}将代码块包含,例如大多数开源的c库的头文件的写法;
  • 如果c头文件中没有加入extern “C”{}的代码块,那么也可以在extern “C”{}中加入包含的c头文件。

实际中是如何发挥作用的

假设b.cpp中要调用int add(int, int)函数,但是add函数是在a.so中定义的,而a.so又是通过a.c和a.h编译而成的。如此一来,a.so中的add函数是类似_add这样的,而b.cpp中在连接时去找_add_int_int这样的函数名,自然找不到,但是如果在a.h中加入extern "C"的申明,则编译b.cpp在链接时就知道应该去找_add,而不应该去找_add_int_int。但是注意,这种情况下extern "C"需要和#ifdef __cplusplus结合使用,因为extern "C"是c++的语法,在c中使用extern "C"会报错。需要了解的是,__cplusplus在c++文件中默认定义,但是在c文件中不会定义,所以如果不加#ifdef _cplusplus,当a.h在c代码中使用时,就会出现编译错误。。示例代码如下:
a.c:

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

a.h

#ifdef __cplusplus
extern "C"
{
#endif

int add(int a, int b);

#ifdef __cplusplus
}
#endif

b.cpp

#include<a.h>
#include<stdio.h>

int main(void)
{
	printf("1+1=%d\n", add(1,1));
	return 0;
}
all:a_so b_exe

a_so:
        gcc -shared a.c -o libaaaa.so

b_exe:
        g++ b.cpp -o b_exe -laaaa -I./ -L./
        @echo "compile b_exe"

clean:
        rm b_exe libaaaa.so

.PHONY: all

上述代码中,在b.cpp中包含了a.h。如果a.h中不加入extern “C”,那么就会出现如下的编译错误:

mokar@ubuntu:~/study/c/extern_C$ make
gcc -shared a.c -o libaaaa.so
g++ b.cpp -o b_exe -laaaa -I./ -L./
/tmp/ccfQXDCP.o: In function main': b.cpp:(.text+0xf): undefined reference toadd(int, int)’
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target ‘b_exe’ failed
make: *** [b_exe] Error 1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
extern "C"的作用是用于实现C和C++之间的相互调用问题。C和C++对于函数名的处理方式是不一样的,所以当我们希望调用其他用C编写的函数时,需要告诉编译器使用不同的要求。通过在C++代码中使用extern "C"来声明函数,可以使编译器按照C的规则来处理函数名和参数排列的顺序,从而实现C和C++之间的兼容调用。 需要注意的是,extern "C"不能在函数内部使用,而是用于函数的声明。如果一个函数有多个声明,可以都加上extern "C",或者只在第一次声明中出现,后面的声明会接受第一个链接指示符的规则。 所以当我们需要在C++代码中调用C函数时,可以使用extern "C"来实现对C函数的调用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【004 关键字】extern “C“的作用是什么?](https://blog.csdn.net/qq_41709234/article/details/123082378)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [extern关键字作用.docx](https://download.csdn.net/download/Stephen___Qin/87567249)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值