一、概述

  在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. cocos2dx 公告效果

    第一种方法: http://blog.csdn.net/jackystudio/article/details/12991977 [玩转cocos2d-x之十六]滚动字幕和公告 第二种方法: http ...

  2. eclipse创建多模块maven工程小结

    创建maven工程步骤 1 新建一个maven工程,如下图所示: 2 选择项目名称(或项目目录),如下图所示: 3 填写maven工程相关信息,注意父maven工程的packing方式是pom,如下图 ...

  3. 根据ip地址从第三方接口获取详细的地理位置

    最近项目某个功能需要根据ip地址从第三方接口获取详细的地理位置,从网上找了很多例子,主要接口有新浪的,淘宝的,腾讯的.试了淘宝的,如果是数量级小的还可以,如果数量级达到上十万级就速度慢了,会导致系统崩 ...

  4. 关于Git中的一些常用的命令

    深入了解git的checkout命令 检出命令(git checkout)是Git最常用的命令之一,同时也是一个很危险的命令. 因为这条命令会重写工作区.检出命令的用法如下: 用法一: git che ...

  5. Divide and conquer method

    分治法是最广泛使用的算法设计方法之一,其基本思想:把大问题分解成一些较小的问题,然后由小问题的解方便地构造出大问题的解. 分治法说穿了就是把问题放小,如果被分的问题还是比较大,那么久继续分下去.为了能 ...

  6. MATLAB基础入门笔记

    为了参加那个电工杯,豁出去啦,时间真的很短,但是得挑战呀..对于MATLAB编程,有一些了解,MATLAB(矩阵实验室的简称)是一种专业的计算机程序,用于工程科学的矩阵数学运算,说说它的开发环境. 任 ...

  7. svn has stoped working

    各种问各种搜  ,看来还得靠自己,,,,下面是解决方案; 如果你出现这种情况,  右键点击svn的选项,就弹出这个框框,,,,点击svn里的哪个选项都是弹出这个框框,,,,重新安装,重启,换各种版本安 ...

  8. hdu 1040 As Easy As A+B

    As Easy As A+B Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  9. mount命令详解

    http://tutu.spaces.eepw.com.cn/articles/article/item/70737 挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount ...

  10. 编译gd-2.0.35.tar.gz时报错:gd_png.c:16:53: error: png.h: No such file or directory

    编译gd-2.0.35.tar.gz时报错: gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/local/freetype/include/freetype2 -I/us ...