extern “C“的作用及理解

2023-05-16

1 意图

extern "C"是C++特有的指令(C无法使用该指令),目的在于支持C++与C混合编程。

2 作用

extern “C”的作用是告诉C++编译器用C规则编译指定的代码(除函数重载外,extern “C”不影响C++其他特性)。

3 原因

为什么要用C规则编译C++代码呢?

因为C和C++的编译规则不一样,主要区别体现在编译期间生成函数符号的规则不一致。

C++比C出道晚,但是增加了很多优秀的功能,函数重载就是其中之一。由于C++需要支持重载,单纯的函数名无法区分出具体的函数,所以在编译阶段就需要将形参列表作为附加项增加到函数符号中。如以下代码

void Function(int a, int b)
{
    printf("Hello!!! a = %d, b = %d\n", a, b);
}

C和C++对应的的汇编码如下

  • C汇编结果
...
Function:
.LFB11:
    .cfi_startproc
    movl    %esi, %edx
    xorl    %eax, %eax
    movl    %edi, %esi
    movl    $.LC0, %edi
    jmp    printf
    .cfi_endproc
...
  • C++汇编结果
...
_Z8Functionii:
.LFB12:
    .cfi_startproc
    movl    %esi, %edx
    xorl    %eax, %eax
    movl    %edi, %esi
    movl    $.LC0, %edi
    jmp    printf
    .cfi_endproc
...

容易发现,两段代码的区别仅在于函数 Function(int a, int b) 编译后对应的符号不同

  • C:Function

  • C++_Z8Functionii

C++编出来的函数符号明显比C的多出了一些信息(如ii),这里多出来的后缀信息就是形参列表的参数类型信息。

好,C和C++编译规则对编译期间产生函数符号的影响我们知道了,但这又有什么用呢?

别急,很多人可能都遇到类似过这样的情况

/* MyFunction.c */
void Function(int a, int b)
{
    printf("Hello!!! a = %d, b = %d\n", a, b);
}


/* main,cpp */
extern void Function(int a, int b);

int main()
{
    Function(1, 2);
}

C提供写了一个函数,用C++代码调用该函数,看起来没什么问题,但是编译的时候...

/tmp/ccbkGl1J.o:在函数‘main’中:
main.cpp:(.text.startup+0xf):对‘Function(int, int)’未定义的引用
collect2: 错误:ld 返回 1

找不到对Function(int, int)的定义?怎么可能?

如果找到就玄幻了,大家注意观察,错误出在哪一步?对,编译阶段没报错,是链接的阶段报错了。我们来看看两个文件的汇编结果

    .file    "MyFunction.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string    "Hello!!! a = %d, b = %d\n"
    .text
    .p2align 4,,15
    .globl    Function
    .type    Function, @function
Function:
.LFB11:
    .cfi_startproc
    movl    %esi, %edx
    xorl    %eax, %eax
    movl    %edi, %esi
    movl    $.LC0, %edi
    jmp    printf
    .cfi_endproc
.LFE11:
    .size    Function, .-Function
    .ident    "GCC: (GNU) 6.4.1 20170727 (Red Hat 6.4.1-1)"
    .section    .note.GNU-stack,"",@progbits
    .file    "main.cpp"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl    main
    .type    main, @function
main:
.LFB0:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $2, %esi
    movl    $1, %edi
    call    _Z8Functionii
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE0:
    .size    main, .-main
    .ident    "GCC: (GNU) 6.4.1 20170727 (Red Hat 6.4.1-1)"
    .section    .note.GNU-stack,"",@progbits

可以看到,MyFunction.s(源文件为.c文件)中定义的是Function,而main.s(源文件为.cpp文件)中调用的是_Z8Functionii,函数名不一样,所以连接的时候找不到函数实现。到这里我们知道C和C++编译期间后得到的函数符号不同,所以C++代码和C代码不能互相调用。

  • 要想实现C、C++混合编程该怎么办呢?让编译后的函数符号一致;

  • 怎么一致呢?用extern "C"!

所以,extern “C”的作用就是告诉C++编译器,将指定的函数用C规则编译(注意,除了函数重载外,extern “C”不影响C++的其他特性),然后后面的事情就顺理成章了。

 

参考链接

https://www.zhihu.com/question/265637582 

https://en.cppreference.com/w/cpp/language/language_linkage 

https://isocpp.org/wiki/faq/mixing-c-and-cpp

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

extern “C“的作用及理解 的相关文章

  • extern和volatile的用法

    extern 的用法 extern的用法的对象主要是变量和函数 用extern声明外部变量 什么是外部变量 外部变量是指在文件或者函数外部定义的全局变量 外部变量仅定义一次并且在所有的函数之外 在一个文件内使用外部变量 作用域 xff1a
  • 什么情况下需要加extern “C“,通俗易懂

    下午看了一些关于extern 34 C 34 的博客 xff0c 都写得很啰嗦 xff0c 看来看去还是有一些细节不怎么了解 xff0c 自己开了个程序测试了一下 xff0c 总结了什么情况下需要加入extern C 首先c 43 43 和
  • extern “C“的作用及理解

    1 意图 extern 34 C 34 是C 43 43 特有的指令 xff08 C无法使用该指令 xff09 xff0c 目的在于支持C 43 43 与C混合编程 2 作用 extern C 的作用是告诉C 43 43 编译器用C规则编译
  • extern “C"作用

    1 在cpp文件中调用c文件中实现的函数的时候 xff0c 需要用extern 34 C 34 声明该函数 xff0c 否则cpp会按名字改编后的 函数名去找该函数而找不到 这是作用 xff09 c文件中有一函数 xff1a void Tr
  • c语言中extern的作用6,[020]extern "C"的作用

    前言 我们用Android Studio新建native的demo应用中 xff0c 一般C 43 43 的代码如下 xff0c 这是一个典型的静态注册JNI的例子 xff0c 调用stringFromJNI的java方法会调用到Java
  • extern "C" 含义

    extern 34 C 34 含义 extern 34 C 34 被 extern 限定的函数或变量是 extern 类型的 被 extern 34 C 34 修饰的变量和函数是按照 C 语言方式编译和链接的 extern 34 C 34
  • extern C的作用详解

    extern 34 C 34 的主要作用就是为了能够正确实现C 43 43 代码调用其他C语言代码 加上extern 34 C 34 后 xff0c 会指示编译器这部分代码按C语言的进行编译 xff0c 而不是C 43 43 的 由于C 4
  • 对extern,static,const的再认识

    const const修饰的值为常量 是不可改变的 在c 语言中是不可改变的 而在C语言中 我们可以通过指针去修改那一片地址的值 const修饰的指针 表面指针指向或者指针的值是不可被修改的 我们可以通过通配符 的位置来判断 在左说明修饰的
  • extern C 在c/c++中的使用

    http blog csdn net jscese article details 37821961 1 问题定义 在研究操作系统源代码或者在嵌入式系统中编写程序时 经常会发现下面这种用法 cpp view plain copy print
  • 两个具有相同名称和类型的变量,在两个不同的.c文件中,使用gcc编译

    事情是这样的 我在两个不同的 c 文件中有两个相同的全局变量 它们没有声明为 extern 所以每个 c 文件应该看到自己的变量 对吧 但我得到了一些非常奇怪的行为 就好像一个文件正在读取其他文件变量 将它们链接在一起之后 向两个变量定义添
  • 声明/定义自定义类 cout 对象的正确方法

    我创建了自己的std cout类似于将两者写入的对象std cout并写入日志文件 我目前在头文件中像这样定义它 但我收到了未使用的变量警告 头文件
  • C 和 C++ 中的 static 和 extern 全局变量

    我制作了 2 个项目 第一个项目使用 C 语言 第二个项目使用 C 语言 两者都具有相同的行为 C项目 header h int varGlobal 7 main c include
  • c 中的外部和全局

    谁能告诉我使用有什么特殊要求吗EXTERN or GLOBALC 程序中的变量 如果我从 gloabl 更改为 extern 我看不出像下面这样的程序有任何区别 include
  • 在头文件中使用 extern 的优点

    这里有一个类似的问题标题 但在阅读答案时 它似乎没有解决该特定问题 C 头文件中的 extern 有什么用 它更像是 为什么使用头文件 在下面的用法中extern extern int a int b structs have no ext
  • 重新定义;不同的基本类型(typedef struct)

    当结构在不同的文件中定义时 我在尝试使结构正常工作时遇到了一些麻烦 据我所知 错误告诉我该结构被定义了两次不同的时间 我相信也许我可能需要在某个地方使用 extern 我尝试过尝试并在 Google 上寻求帮助 但没有成功 任何帮助将不胜感
  • 初始化并声明为“extern”,为什么我看到下面的警告? [复制]

    这个问题在这里已经有答案了 为什么我会看到以下警告 警告 i 已初始化并声明为 extern include
  • 局部变量和寄存器变量可以声明为 extern 吗?

    我一直想知道是否可以在本地声明 extern 和寄存器变量 如果可以的话 会受到什么限制 在某些情况下 局部变量可以声明为 extern 让我们来读一下C99 N1256标准草案 http www open std org JTC1 SC2
  • 在定义中使用 static 关键字与在 C 中使用声明

    以下编译良好 使用static仅在函数声明期间 include
  • 关于静态数据成员和成员函数定义的 Extern 关键字,C++

    C 标准是否允许extern静态数据成员和成员函数定义上的关键字 假设链接匹配 例如 struct A static int a external linkage void f external linkage extern int A a
  • 如何编译Freetype(2)和Harfbuzz(使用Visual Studio)以使它们协同工作?

    我找到了关于编译与 Harfbuzz 相关的 Freetype 的已知问题的良好文档 http www gregwessels com dev 2017 05 02 freetype harfbuzz html http www gregw

随机推荐

  • raspberry pi 3 ModelB 更换内核、文件系统初探

    1 镜像烧录 1 下载官方最新镜像 xff1a https www raspberrypi org downloads 2 Win32DiskImager烧录 xff1a https sourceforge net projects win
  • char类型与int类型的相互转换、

    相关知识 xff1a 1 计算机中的一个unsigned char型数据表示0 255 xff0c 而一个signed char型数据表示 128 43 127 xff0c 都是256的数字 这256个数字 xff0c 在计算机的存储单元都
  • 使用printf输出各种格式的字符串

    xfeff xfeff 分类 xff1a 43 43 主题 使用printf输出各种格式的字符串 日期 2004 06 29 43 43 1 原样输出字符串 printf 34 s 34 str 2 输出指定长度的
  • float型变量和“零值”比较的方法

    前一段时间读了一下林锐博士的 高质量C C 43 43 编程指南 xff0c 其中有一个比较经典的问题 请写出float x与 零值 比较的if语句 xff1f 当时只知道不能直接用float类型的值与0进行 61 61 或 61 比较 x
  • 全局变量和局部变量

    全局变量也称为外部变量 xff0c 它是在函数外部定义的变量 它不属于哪一个函数 xff0c 它属于一个源程序文件 其作用域是整个源程序 在函数中使用全局变量 xff0c 一般应作全局变量说明 只有在函数内经过说明的全局变量才能使用 但是在
  • c 内存管理

    其他相关链接 xff1a https blog csdn net wind19 article details 5964090 一 几个基本概念 在C语言中 xff0c 关于内存管理的知识点比较多 xff0c 如函数 变量 作用域 指针等
  • Springboot操作MongoDB,包括增改查及复杂操作

    单条件查询 使用BasicDBObject配置查询条件 List span class token generics function span class token punctuation lt span AbstractMongoEn
  • 搭建Spark实战环境(3台linux虚拟机集群)(一)样板机的搭建

    系统及软件配置 系统配置 内存 xff1a 16g 2400 cpu xff1a i5 9400F 软件配置 Windows 10 1903版本VMware workstation 15 10CentOS centos release 7
  • 独立个人项目开发心得 - 任务切分、挑战性、实用性和半途而废

    在写文章前容许我啰嗦一下 xff1a 对于软件开发 xff0c 我走了不少弯路 xff0c 有时觉得自己作为API侠 xff0c 无所不能 xff0c 有时又觉得自己很多LeetCode题写不出来 xff0c 无能为力 我有一个博客 xff
  • 传统软件服务器与游戏服务器架构区别

    项目智能客服爬虫SLG游戏语言javapythonkotlin模型异步事件驱动可能没什么模型可言actor模型传输协议httphttptcp 43 netty传输结构jsonjsonprotobuf数据库oracle xff0c redis
  • Linux C++ Socket实战

    本文主要介绍Linux C 43 43 基础Socket网络编程 大部分知识来自于网站 xff1a https www geeksforgeeks org socket programming cc Socket编程状态图 从图中可以看到
  • CSAPP第二章-信息的表示与处理-随手记

    仅作为学习 深入理解计算机系统 第二章时的笔记 xff0c 仅记录对自己有启发的部分 xff0c 不作为知识整理 xff08 直接看电子书就可以了 xff09 因为这本书知识点非常多 xff0c 所以我会抽时间多次阅读 xff0c 本文也会
  • Vue的路由配置及手动改地址栏为啥又跳转回来??

    vue cli xff08 vue脚手架 xff09 超详细教程 xff1a https blog csdn net wulala hei article details 85000530 这个教程里面是使用 vue init webpac
  • GPS卫星轨道

    GPS卫星轨道周期几乎是24小时 xff0c 而自己的卫星在太阳同步轨道上的周期大概是1 5个小时 xff0c 那么就是说太阳同步轨道已经绕几周了 xff0c GPS卫星才饶一周 所以当算多普勒频移的时候只需要算出GPS一个周期时间内的多普
  • 快速了解S7-1200 PLC的存储器及存储区的寻址方式

    S7 1200 PLC的存储器地址包括输入I 输出Q 位存储器M 数据块DB xff0c 以及本地或临时存储器L eg xff1a 标识存储区M0 0 MB0 MW0 MD0 分别是 B位 字节B 8位 字W 16位 双字D 32位 输入过
  • 网络编程之UDP简单示例

    UDP编程函数recvfrom inet pton sendto UDP协议 user data protrol 用户数据协议特点 xff1a TCP xff1a 面向连接 gt 一定双方连接上了才能进行通信 xff01 UDP xff1a
  • 微信开发(二)http请求工具类

    说明 进行微信开发 xff0c 后台程序需要与微信服务器进行交互 xff0c 通过调用接口来完成服务 xff0c 阅读微信开发文档 xff0c 发现接口的调用都是通过http请求进行的 xff0c 所以必须有个HttpUtil来支撑 xff
  • STM32寄存器与结构体

    piaolin 发表于 2015 9 30 01 02 只看该作者 倒序浏览 阅读模式 第16集 蜂鸣器实验 这个实验和流水灯是一样的 xff0c 只是将相对应的IO口拉高拉低即可控制蜂鸣器 值得注意的是电路设计方面 xff0c 根据视频描
  • 字节序

    1 字节序 字节序 xff0c 又称端序或尾序 xff0c 指的是多字节数据在内存中的存放顺序 例如一个int型变量x占用4个字节 xff0c 假设它的起始地址 amp x为0x10 xff0c 那么x将会被存储在 0x10 0x11 0x
  • extern “C“的作用及理解

    1 意图 extern 34 C 34 是C 43 43 特有的指令 xff08 C无法使用该指令 xff09 xff0c 目的在于支持C 43 43 与C混合编程 2 作用 extern C 的作用是告诉C 43 43 编译器用C规则编译