一、概述

  在C语言的头文件中,经常可以看到如下的代码,那这个是什么作用呢?

#ifdef __cplusplus
extern "C" {
#endif /*...*/ #ifdef __cplusplus
}
#endif

  extern "C"起作用的时候是在:C++调用C中的函数。由于C++和C是两种不同的编译和连接方法,所以在交叉调用的时候,就需要增加一些机制起到让两者无缝兼容的目的。而extern "C"正是这一种机制,规定在编译C++源文件时,那些调用自C文件的部分(需要用extern "C"修饰其在头文件中的声明),按照与C文件编译兼容的方式进行。

  那么显然在不涉及C++调用C中函数的情况,extern "C"是不起作用的。在编译C文件的时候,编译器是不会自动添加“__cplusplus”的宏定义;而在编译C++文件的时候,编译器会自动的对“__cplusplus”进行宏定义。

二、C++的编译

1、测试源码

  • config.c
void config(void)
{
return ;
}
  • config.h
#ifndef    __CONFIG_H
#define __CONFIG_H extern void config(void); #endif
  • main.cpp
#include "config.h"
int main(void)
{
...
config();
...
}

2、测试

  使用arm-none-eabi-gcc交叉编译链对以上源码进行编译,arm-none-eabi-gcc工具编译config.c,arm-none-eabi-g++编译main.cpp,结果如下:

  config.o.lst

                        .section    .text.config,"ax",%progbits
.align
.global config
.thumb
.thumb_func
config:
.LFB30:
config:
.LFB30:
:../User/config.c ****
:../User/config.c **** void config(void)
:../User/config.c **** {
.loc
.cfi_startproc
@ args = , pretend = , frame =
@ frame_needed = , uses_anonymous_args =
@ link register save eliminated.
80B4 push {r7}
.cfi_def_cfa_offset
.cfi_offset , -
00AF add r7, sp, #
.cfi_def_cfa_register
:../User/bsp_led.c **** return ;
.loc
00BF nop
:../User/bsp_led.c **** }
.loc
BD46 mov sp, r7
@ sp needed
5DF8047B ldr r7, [sp], #
000c bx lr

  main.o.lst

  :../User/main.cpp ****     config();
.loc
FFF7FEFF bl _Z6configv

 在连接程序的最后阶段,出现错误提示:../User/main.cpp:35: undefined reference to `config()'

原因分析:

  因为config.c程序在编译的时候被翻译成了.text.config代码段,而此段中存在一个函数标号config。也就是说config.c文件的config()函数在编译的时候,其对应的标号是config

  而main.cpp文件调用该函数的地方,编译后却使用了标号_Z6configv。那么显然在连接的时候,连接器无法将这两个标号连接到一起,而出现上述错误。

3、使用extern “C”关键字

  修改config.h,内容为

#ifndef    __CONFIG_H
#define __CONFIG_H extern "C" void config(void); #endif

  重新编译这些文件,结果main.cpp的编译结果出现了变化,而最终程序连接也通过了

  :../User/main.cpp ****     config();
.loc
FFF7FEFF bl config

原因分析:

  由于extern "C"修饰了void config(void),所以在main.cpp调用该函数的时候按照C文件的编译方式进行编译,所以其对应的标号为config。config函数所在的文件config.c文件编译出的标号与之一致,就能成功的连接。

参考博客:C++项目中的extern "C" {}

extern "C"的作用的更多相关文章

  1. extern C的作用详解

    extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C+ ...

  2. C++编译时函数名修饰约定规则(很具体),MFC提供的宏,extern "C"的作用

    调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数 ...

  3. extern “C”的作用详解

    extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C+ ...

  4. C++之 extern C的作用详解

    extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C+ ...

  5. extern "c" 的作用

    作用:实现C和C++混合编程. 原理:C和C++编译器编译之后,函数名会编译成不同的名字,链接阶段名字查找会找不到目标,后面实例中会详解. 用法:①.c文件中定义的函数,.cpp文件要调用时,该.cp ...

  6. extern “C”的作用

    1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++保留了一部分过程 式 ...

  7. [转]extern "C"的作用

    extern "C"的主要作用就是为了能够正确实现C++代码调用其它C语言代码. 加上extern “C”后,会指示编译器将这部分代码按C语言进行编译,而不是C++的.这是因为C+ ...

  8. extern C的作用具体解释

    转载于:http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html 1.引言 C++语言的创建初衷是"a better ...

  9. 你真的知道C语言里extern "C" 的作用吗?

    经常在C语言的头文件中看到下面的代码: #ifdef __cplusplus extern "C" { #endif // all of your legacy C code he ...

随机推荐

  1. C#_mvc_ajax_return data

    假设cshtml文件中是这样的: <script type="text/javascript"> $(document).ready(function(){ $(&qu ...

  2. 用antlr文法编写的hermit swrl规则(分享)

    /* * To change this license header, choose License Headers in Project Properties. * To change this t ...

  3. 如何使用MVP模式搭建我们的Android应用?

    听到很多人在讨论MVVM,我自己早些时候也写过一篇介绍MVVM的文章(玩转Android之MVVM开发模式实战,炫酷的DataBinding!),实际上,在Android开发领域中,除了MVVM之外, ...

  4. How to use BMW Multi Tool 7.3 to replace lost key for BMW X1

    BMW Multi Tool 7.3 version is a high quality auto key programmer that supports CAS 1, CAS2, CAS3, CA ...

  5. h5拖放-ff的bug

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. FastDFS为什么要结合Nginx

    FastDFS为什么要结合Nginx? 我们在使用FastDFS部署一个分布式文件系统的时候,通过FastDFS的客户端API来进行文件的上传.下载.删除等操作.同时通过FastDFS的HTTP服务器 ...

  7. react 全局面包屑

    renderBreadcrumb() { const {routes} = this.props; const items = routes.map((route, idx) => { let ...

  8. asp实现关键词不区分大小写搜索并高亮显示

    用ASP做搜索很容易,但要实现智能搜索这类就比较累一点,其实任何程序都差不多,主要还是看数据库的处理能力,一般小网站ASP经常跟ACCESS数据库搭配,在这种配置下我们要实现关键词不区分大小写搜索并高 ...

  9. poj2337 欧拉路径

    poj2337 这道题昨天晚上开始做,今天才A.但是问题想透了, 发现其实没那么难 题目大意: 给你一些单词,如果一个单词的末尾字符与另一个单词首字符相同,则两个的单词可以连接.问是否可以把所有单词连 ...

  10. redhat6.5 配置使用centos的yum源

    新安装了redhat6.5安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription Ma ...