首页 技术 正文
技术 2022年11月23日
0 收藏 896 点赞 3,583 浏览 1824 个字

一、概述

  在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_Hextern 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_Hextern "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” {}

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,965
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,486
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,331
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,114
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,747
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,781