首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么clang要从声明为'extern "C"‘的函数中删除下划线?

clang是一个开源的C语言编译器,它被设计用于兼容标准的C和C++代码的编译。在C++中,为了兼容C语言的函数命名规则,可以使用extern "C"来声明一个C语言的函数接口。这样做可以使C++编译器按照C语言的规则进行函数名的解析和链接。

在一些编译环境中,C语言的函数名会在函数名前面添加一个下划线,而C++函数名不会添加下划线。然而,由于历史原因和不同编译器的实现差异,一些编译环境中会为extern "C"声明的函数在函数名前面添加两个下划线。

为了解决这个问题,clang编译器默认情况下会从声明为extern "C"的函数中删除下划线。这样做的目的是为了保持和其他编译器的兼容性,以及提供更一致的行为。

删除下划线的操作是由clang编译器内部的命名修饰器(name mangler)完成的。通过删除下划线,extern "C"声明的函数可以在C++代码中以一致的方式调用和链接,而不会受到特定编译环境的影响。

总结来说,clang删除从声明为extern "C"的函数中删除下划线是为了保持和其他编译器的兼容性,提供一致的行为,并使extern "C"声明的函数可以在C++代码中以一致的方式调用和链接。

关于腾讯云相关产品,由于答案要求不提及具体品牌商,无法给出腾讯云相关产品的介绍链接地址。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

深入iOS系统底层之程序中的汇编代码

一个汇编语言文件中还可以使用和C语言类似的文件引入以及各种预编译指令,还可以引用高级语言中定义的变量和符号以及函数。 1.注释 汇编指令中注释和C/C++/OC相同。...高级语言文件中定义的能被外部访问的函数和全局变量其实都是一个符号,不管是函数地址还是全局变量的内存地址,其实都是一个地址位置,而地址的别名则是可以用标签表示,因此要想将一个标签定义为外部可访问,就需要将标签名声明为符号....private_extern 私有外部符号名 私有外部符号名: 符号名要和标签名匹配。因为C语言的函数名称以及全局变量等符号在编译时生成的符号前面添加一个下划线_。...这里面p2align貌似和align所表达的意义相似,不知道为什么会有两个关键字。 .align 3 .p2align 3 5.宏定义 汇编语言也可以和C语言一样使用宏定义,来做一些代码复用处理。...所以当你在其他文件中要想使用汇编语言中定义的函数或者全局变量时,可以在你的源代码文件的顶部进行符号使用的声明: //xxxxx.m //函数声明 extern void 不带下划线的函数符号(参数列表

1.7K30
  • 弱符号__attribute__((weak))

    弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误。...链接器会忽略弱符号,去使用普通的全局符号来解析所有对这些符号的引用,但当普通的全局符号不可用时,链接器会使用弱符号。当有函数或变量名可能被用户覆盖时,该函数或变量名可以声明为一个弱符号。...attribute((weak))的作用 情况是这样的,碰到一个棘手的问题:我们不确定外部模块是否提供一个函数func,但是我们不得不用这个函数,即自己模块的代码必须用到func函数: extern int...在自己的模块中定义: int __attribute__((weak)) func(......) { return 0; } 将本模块的func转成弱符号类型,如果遇到强符号类型(即外部模块定义了...main.c #include extern void real_func(); void main() { real_func(); } 如果 gcc main.c

    6.5K30

    C语言的数据类型

    除库函数的函数名由系统定义外,其余都由用户自定义。 C规定,标识符只能是字母(A~Z,a~z)、数字(0~9)、下划线(_)组成的字符串,并且其第一个字符必须是字母或下划线。...例如在某版本C 中规定标识符前八位有效,当两个标识符前八位相同时,则被认为是同一个标识符。   (2)在标识符中,大小写是有区别的。例如CLANG和Clang 是两个不同的标识符。   ...数据类型和关键字 在程序的世界中,承载一系列的信息的数字和字符都属于数据类型,但计算机需要一种方法来区别和使用这些不同的类型。具体的,C通过识别一些基本的数据类型做到这些。...关键字 在c语言中,为了定义变量、表达语句功能和对一些文件进行预处理,还必须用到一些具有特殊意义的字符,这就是关键字,我们用户自己定义的变量函数名等要注意不可以与关键字同名。...C语言中的32个关键字 auto double int struct break else long switch case enum register typedef char extern return

    2.5K50

    module & Swift库

    export A表示将B.h导入的A.h头文件重新导出 通过clang命令,开启module并将use.c编译成目标文件clang -fmodules -fmodule-map-file=module.modulemap...,外界如何使⽤Swift中public修饰的类和函数?...OC的编译器,当前就是clang 加载modulemap文件的路径 对应Build Setting中的配置项 打开ViewController.m,写入以下代码: #import "ViewController.h...NS_REFINED_FOR_SWIFT:通过指定NS_REFINED_FOR_SWIFT宏,Swift的Clang Importer将做一些额外的工作,将该方法导入为私有方法,并以双下划线字符__开头...命令,合并静态库本身 用到的头文件、Swift头文件以及modulemap文件,通过目录的形式放到一起 OC要用合并的静态库:clang: other c flags:-fmodule-map-file

    2.1K45

    从Xcode10不再支持libstdc++说起

    目前比较流行的C++编译器有微软的VC++,GNU组织的gcc(g++), 苹果的LLVM(clang++)等。...你可以从这个类中查看一个C++类的名称,数据成员和函数布局的信息,type_info中的信息就类似于OC的isa所指向的Class类型是一样的。...Xcode对C++的支持和设置 Xcode中建立的工程项目可以选择使用的C++的方言和C++的标准库版本,在工程的Build Settings中的Apple Clang - Language - C++...为什么可以在一个工程中可以同时引入两个定义了相同内容的类库呢?难道不会在编译时报符号冲突或者重名的错误吗?...我们知道libc++中的内容是libstdc++中的超集,为什么在同时引入两个库时不会报函数或者类名冲突呢? 答案就是C++11中提供了对inline namespace的支持。

    2.2K30

    C#调用GDI+1.1中的函数实现高斯模糊、USM锐化等经典效果。

    其实,这些函数我在VB6下两年前就已经调用过,调用的方式也很简单明了,现在,在学习C#,就要考虑如何将他们封装入C#中。...实现这个功能的第一步就是要找到这些函数的声明,这个在MSDN上有C风格的声明,改成C#语言的大部分都不成问题,参考 http://msdn.microsoft.com/en-us/library/ms533971...C#的Bitmap类的,或者你也可以声明为HandleRef类型的,VS就是这么干的, 对于最后几个参数,是用来给用户返回一些数据,基本上不会有人对那几个数据感兴趣,因此你声不声明为out类型的参数也无所谓...问题来了,第一个参数bitmap的本意是GDI+的image对象的句柄,在C#中,有Bitmap类,实际上我们知道他就是GDI+的封装,那么他的具体的实例中肯定也对应了一个GDI+对象的句柄,但是他封装的太厉害了...要从其中获取字段值的对象 /// 字段的名称.

    1.9K40

    99%开发者从未听说过的堆栈模型(加量增强版)

    在中文嵌入式环境中,时不时的总能看到不少朋友”堆”“栈“傻傻分不清楚,我很早之前在文章《漫谈C变量——夏虫不可语冰》介绍过二者的区别,这里就不再深入展开,总之: 栈(Stack)“是我们用来分配局部变量...、实现函数调用和在异常响应时保存被打断代码上下文的地方——具体细节不重要,在本文的讨论中,我们只需要记住以下信息: Cortex-M系统栈的生长方向是自上而下的,也就是随着更多内容被压入(PUSH)栈中...“堆(Heap)”是我们使用 malloc 申请动态存储空间时所必须用到的一种数据结构——通常由C语言的系统库提供。...——Heap的尺寸应该就是使用整个 RAM的终止地址减去 RW_IRAM1 的终止地址啊,为什么提示差4个字节呢?...__) # pragma clang diagnostic pop #endif 【后记】 ---- 在这篇文章中,我们介绍了栈和堆在存储器中的常见排布模型,比较了它们的优劣,并提出了一种被称为“两面包夹芝士

    2K30

    【计算机本科补全计划】C++ Primer 第二章 【变量和基本类型】

    for (unsigned i = 10; i >=0; --i) { cout<<i<<endl; } 在上面的函数中,你永远也到不了-1,因为无符号数本身的定义中就没有-1,0-1的结果是当前的位数最大值...如果是定义于函数体外的变量会默认初始化为0,而函数体内的内置函数变量不被初始化,即未定义初始化值。 当然,对于类,如果在类的定义中有初始化的值,就不需要函数体来操心了。...如果声明一个变量而不是定义,那么加一个关键字extern 。 extern int j; // 声明j而不是定义,还没有分配内存空间。...6、 标识符 C++的标识符由字母,数字,下划线构成,并且标识符的开头只能是字母或者下划线而不能是数字。并且标识符对大小写敏感。 书上有说两个要求,但是我实际跑的时候没报错,也许是我的自动更正了?...如下(毫无压力): 不能连续出现两个下划线 ; 不能以 下划线紧接着大写字母开头; 函数体外的标识符不能以下划线开头。

    706110

    C++调用C函数

    前言:以前见到extern "C"这样的语句,只是简单地知道跟外部链接有关,但是没有深刻理解它的意思。 首先,为什么要使用extern "C"修饰符?...C++调用其它语言的函数,由于编译器生成函数的机制不一样,所以需要经过特殊处理,才可以调用。调用C语言的函数,需要在函数声明的地方语句extern "C"。...刚开始,我简单地在C++源文件的前面使用该语句声明,但是还是出错,而且是在编译阶段就报错。 error C2732: 链接规范与“DeleteStack”的早期规范冲突。 为什么会出现这个错误呢?...因为C++源文件已经引入了C的头文件,在头文件里,声明该函数时没有extern修饰,而这里有extern修饰,所以冲突了。解决的办法有两个。 一。在C头文件中加上extern修饰符。 直接加,也不行。...以上为单个形式,复合形式可以同时将几个函数声明为extern "C" extern "C" { void DeleteStack(Stack stack); void PrintStack(Stack

    2.8K40

    实例说明

    那么,为什么C语言没有内置的输入输出语句呢? 一个答案是并非所有的程序都要用到I/O(输入/输出)包,并且C语言的一个基本的设计原则就是避免不必要的成分。...每个C程序中必须有它! 那么圆括号的功能呢?它表明main()是一个函数。以后,我们将遇到更多的函数。现在,请记住这个函数就是C程序的基本模块。 int指明main()函数的返回类型。...把一个变量声明为整数类型或字符类型是计算机正确地存储,获取和解释该数据的基本前提。在后面您将学到各种各样的可用类型。...第一个字符必须是字母或者下划线。 C语言的名字是区分大小写的,即把一个大写字母和与之对应的小写字母看作是不同的。因此,clang不同于Clang或者CLANG。 六....; printf ("I am clang.cc\n"); printf ("My birthday is %d\n", num); 所有这些行都使用了 C语言的一个标准函数:printf()。

    1.4K80

    python057_如何删除print函数_dunder_builtins_系统内建模块

    用到了 下划线位置作用放后面避免名字冲突添加图片注释,不超过 140 字(可选)为什么 很多本地变量 两边 都有 两个下划线__name____doc____builtins__有什么说法吗??...,不超过 140 字(可选)两边双下划线 代表 系统定义的标识符比如__builtins__添加图片注释,不超过 140 字(可选)突然发现print函数不在本地删除 可以删除print函数吗?...添加图片注释,不超过 140 字(可选)如何调用模块中的函数来着?回忆火星文 添加图片注释,不超过 140 字(可选)新艺术 是怎么清屏的呢?...print 就是__builtins__ 模块里的 函数添加图片注释,不超过 140 字(可选)能删除吗?...有17个字符发音是6声而dunder 只有6个字符发音是2声简单多了添加图片注释,不超过 140 字(可选)dunder 意味着 这个变量 是 系统定义 的!

    4800

    利用Clang探究__block的本质

    那么问题来了,为什么被__block说明符修饰的变量就可以在block函数体内部访问呢?__block底层究竟对被修饰的变量做了什么呢?__block是如何将“外部变量”从栈中转移到堆中?...源码分析 和上一篇文章一样,我们还是在main.m文件中定义一个main函数,并使用clang对这个main函数进行rewrite,使其转换为C++源码,通过C++源码窥探__block底层实现。...答案在构造函数的第一个参数中,构造函数的第一个参数是__main_block_func_0,上面我们说过,__main_block_func_0是一个函数,而上篇文章中也说过,C和C++语言中函数名就是函数指针...分析下来,不难发现,以上main函数的C++层面的执行过程和利用Clang探究block的本质中所述简直一模一样。...在一个文件内定义的全局变量,在另一个文件中,通过extern声明全局变量,就可以使用全局变量;static修饰的全局静态变量,作用域是声明此变量所在的文件。

    7.3K20

    iOS 启动优化--二进制重排

    --> Order File中设置自定义的.order后缀的文件路径,将需要重排的符号按顺序写在里面,当Xcode编译时会按照.order文件中的符号顺序加载,我们可以通过下面几种方法获得APP启动时的运行函数...HOOK objc_msgSend:由于objc_msgSend的参数是可变的,需要汇编获取,而且只能获取到OC方法和Swift中的@objc方法 静态扫描:扫描 Mach-O文件中的 特定段和节里面所存储的符号以及函数数据...Clang插桩:批量100%符号获取,OC、Swift、C都可以获取 Clang插桩 通过LLVM内置的工具SanitizerCoverage,可以在函数级、基本快级和边缘插入到用户定义函数的调用,...官方文档clang 自带代码覆盖工具 中有使用简介和demo 【第一步】 开启SanitizerCoverage oc项目中,Build Settings --> Other C Flags 中添加-...)); } 【第三步】 获取所有符号并写入文件保存 循环取出所有符号 数组取反,因为是入队存储是反序的 数组去重 符号保存到yp.order文件中 extern void getOrderFile(void

    1.3K60

    C++调用C链接库会出现的问题

    add@@YAHHH@Z[/email]),原因是找不到add的目标模块 这才令我想起C++重载的函数命名方式和C函数的命名方式,让我们回顾一下:C中函数编译后命名会在函数名前加以"_",比如add函数编译成...obj文件时的实际命名为_add,而c++命名则不同,为了实现函数重载同样的函数名add因参数的不同会被编译成不同的名字 例如 int add(int , int)==>add@@YAHHH@Z, float...编译cpp.cpp中编译器在cpp文件中发现add(1, 0);的调用而函数声明为extern int add(int x, int y);编译器就决定去找[email=add@@YAHHH@Z]add...add(int, int);}编译器就会知道 add(1, 0);调用的C风格的函数,就会知道去c.obj中找_add(int, int)而不是[email=add@@YAHHH@Z]add@@YAHHH...@Z[/email]; 这也就为什么DLL中常看见extern "C" {},windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL,而用户可能会使用C++而extern "C" {}就会发生作用

    1.1K30

    BPF的可移植性和CO-RE (Compile Once – Run Everywhere)

    首先会调研BPF本身的可移植性问题,描述为什么这是个问题,以及为什么解决它很重要。然后,我们将介绍解决方案中的高级组件:BPF CO-RE,并简要介绍实现这一目标所需要解决的难题。...不同的内核版本会在结构体内部混用结构体字段,甚至会转移到新的内部结构体中。结构体中的字段可能会被重命名或删除,类型可能会改变(变为微兼容或完全不同的类型)。...使用BCC,可以将BPF程序的C代码以字符串的形式嵌入到用户空间的程序中,当程序最终部署并运行在目标主机上后,BCC会唤醒其嵌入的Clang/LLVM,提取本地内核头文件(必须确保已从正确的kernel-devel...BTF是一种节省空间,紧凑但仍具有足够表达能力的格式,可以描述C程序的所有类型信息。由于其简单性和使用的重复数据删除算法,与DWARF相比,BTF的大小可减少多达100倍。...类型名称中的三个下划线以及其后的所有内容均被视为此结构的“flavor”。

    1.4K20
    领券