zoukankan      html  css  js  c++  java
  • extern "C"的作用

    一、概述

      在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

      94                      .section    .text.config,"ax",%progbits
      95                      .align    2
      96                      .global    config
      97                      .thumb
      98                      .thumb_func
     100                  config:
     101                  .LFB30: 
     100                  config:
     101                  .LFB30:
      61:../User/config.c **** 
      62:../User/config.c **** void config(void)
      63:../User/config.c **** {
     102                      .loc 1 63 0
     103                      .cfi_startproc
     104                      @ args = 0, pretend = 0, frame = 0
     105                      @ frame_needed = 1, uses_anonymous_args = 0
     106                      @ link register save eliminated.
     107 0000 80B4             push    {r7}
     108                      .cfi_def_cfa_offset 4
     109                      .cfi_offset 7, -4
     110 0002 00AF             add    r7, sp, #0
     111                      .cfi_def_cfa_register 7
      64:../User/bsp_led.c ****     return ;
     112                      .loc 1 64 0
     113 0004 00BF             nop
      65:../User/bsp_led.c **** }
     114                      .loc 1 65 0
     115 0006 BD46             mov    sp, r7
     116                      @ sp needed
     117 0008 5DF8047B         ldr    r7, [sp], #4
     118 000c 7047             bx    lr

      main.o.lst

      35:../User/main.cpp ****     config();
      42                         .loc 1 35 0
      43 0008 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的编译结果出现了变化,而最终程序连接也通过了

      35:../User/main.cpp ****     config();
      42                      .loc 1 35 0
      43 0008 FFF7FEFF         bl    config

    原因分析:

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

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

  • 相关阅读:
    深入理解乐观锁与悲观锁
    mysql5.7 安装常见问题
    nginx 前后分离,地址重写,url匹配中遇到的问题
    nginx rewrite
    Nginx location 配置
    Nginx高级应用之Location Url 配置
    Zookeeper的功能以及工作原理
    [PY3]——IO——文件目录操作
    [PY3]——pwd | grp 模块
    [PY3]——时间处理——datetime | calendar
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3831483.html
Copyright © 2011-2022 走看看