C++编译器的函数名修饰规则
我们知道在C++中有函数重载这样一个东西,当我们定义了几个功能类似且函数名是一样的函数的时候,只要它的参数列表不同,编译是可以通过的,但是在C中是不可以的。
double add(double a, double b)
{
return a + b;
} int add(int a, char b)
{
return a + b;
}
char add(char a, char b)
{
return a + b;
}
如果这样写的代码,在C中会报出errorC2371,说是add函数重定义。但是如果在C++环境下这样是允许的,叫做函数的重载,只要你的几个函数符合函数重载的要求,是完全没有问题的。这就引出了在C和C++中函数名的修饰规则,为什么在C 中就是不行的?
double add(double a, double b);
//{
// return a + b;
//}
我把这个函数的定义改为声明,然后在main函数中调用,就可以看到提示中的
1. C编译器的函数名修饰规则
编译器给我们报出了一个链接错误,可以看到_add这样的函数,这就是在C环境下编译器对我们函数名的修饰,可以看到是在函数的前面加上下划线,当然这种修改实在默认调用约定__cdecl的情况下,如果在__stdcall调用约定,编译器和链接器会在输出函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其参数的字节数,__fastcall调用约定在输出函数名前加上一个“@”符号,后面也是一个“@”符号和其参数的字节数。
我们可以修改一下调用约定,看看是不是这样的。
这样修改之后再看看,可以看到add函数被修饰为_add@16.所以在不同调用约定下修饰规则也是有所不同的。
1. C++编译器的函数名修饰规则
然后,再看看在C++环境下,编译器对我们的函数是怎样修饰的:
可以看到,对于我声明的double add(double a,double b)函数,被修饰为 (?add@@YANNN@Z),可以看到,这和在C环境中是完全不一样的,所以这也是在C++中有函数重载的原因,那么来看看这到底是怎么修饰的。
C++的函数名修饰规则有些复杂,但是信息更充分,通过分析修饰名不仅能够知道函数的调用方式,返回值类型,参数个数甚至参数类型。不管__cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字,再后面是参数表的开始标识和按照参数类型代号拼出的参数表。对于__stdcall方式,参数表的开始标识是“@@YG”,对于__cdecl方式则是“@@YA”,对于__fastcall方式则是“@@YI”。参数表的拼写代号如下所示:
X--void
D--char
E--unsigned char
F--short
H--int
I--unsigned int
J--long
K--unsigned long(DWORD)
M--float
N--double
_N--bool
U--struct
可以看到N是代表double类型,那么 (?add@@YANNN@Z)就能理解了,函数修饰符?,接着是函数名字,然后是_cdecl约定的开始标示符@@YA然后连着的是返回值类型,参数列表的参数类型刚好是,那么double add(double a,double b)就是NNN,参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。
还有当参数列表有指针的时候,指针的方式有些特别,用PA表示指针,用PB表示const类型的指针。后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复。
举一个简单的例子: int fun(int *p1, int *p2);
可以看到,我的fun函数被修饰为(?fun@@YAHPAH0@Z)。
还有在C++中的成员函数中公有和私有的成员函数的修饰也有相应的表示符。总而言之,在C++环境中的函数名修饰的时候,会带有参数列表的信息,还有返回值的信息,所以在C++中的函数重载就是允许存在的,因为它可以根据你的参数列表选择对应的函数,而显然在我们的C环境下是不允许的。
C++编译器的函数名修饰规则的更多相关文章
- C/C++函数调用的几种方式及函数名修饰规则以及c++为什么不允许重载仅返回类型不同的函数
我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预 ...
- C++编译时函数名修饰约定规则(很具体),MFC提供的宏,extern "C"的作用
调用约定: __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数 ...
- [转][C/C++]函数名字修饰(Decorated Name)方式
1.C/C++函数修饰名: 对于我们的C/C++源程序而言,函数名只是函数的一小部分,函数还有调用方式(参数入栈方式).返回值类型.参数个数和各参数类型等信息,对于C++类成员函数,还有更多信息.这些 ...
- VS2015 编写C++的DLL,并防止DLL导出的函数名出现乱码(以串口通信为例,实现串口通信)
参考链接:https://blog.csdn.net/songyi160/article/details/50754705 1.新建项目 建立好的项目界面如下: 接着在解决方案中找到[头文件]然后右击 ...
- dll 导出函数名的那些事
dll 导出函数名的那些事 关键字: VC++ DLL 导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...
- 函数的调用规则(__cdecl,__stdcall,__fastcall,__pascal)
关于函数的调用规则(调用约定),大多数时候是不需要了解的,但是如果需要跨语言的编程,比如VC写的dll要delphi调用,则需要了解. microsoft的vc默认的是__cdecl方式,而windo ...
- C++ 动态库导出函数名“乱码”及解决
C++ 动态库导出函数名“乱码”及解决 刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都“乱码”了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // ...
- 【图文】[新手]C++ 动态库导出函数名“乱码”及解决
刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都"乱码"了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // 下列 ifdef ...
- C++ 编写的DLL导出的函数名乱码含义解析
C++编译时函数名修饰约定规则: __stdcall调用约定: 1.以"?"标识函数名的开始,后跟函数名: 2.函数名后面以"@@YG"标识参数表的 ...
随机推荐
- 关于ORACLE的硬解析和软解析与MySQL的查询缓存query_cache探讨
今天在项目中探讨到Oracle对于SQL语句的解析方法以及MySQL相应的处理方法: --------------------------------------------------------- ...
- Hellow world!
其实一年前开始就有了些许开篇技术博客的想法,一直觉得写这些的人都一定好牛×.现刚毕业,我也是时候朝牛×之路迈进了.当然,我才刚入门不久,前路漫漫,需一步一脚印,先打算把平常遇到的一些问题与关注的东西都 ...
- UVALive 7281 Saint John Festival (凸包+O(logn)判断点在凸多边形内)
Saint John Festival 题目链接: http://acm.hust.edu.cn/vjudge/contest/127406#problem/J Description Porto's ...
- Linux上svn服务器的搭建
安装svn服务器 直接用yum安装,命令如下: #yum install -y subversion 验证是否安装成功. #svnserve --version 创建SVN版本库 在home目录下创建 ...
- UVaLive 6623 Battle for Silver (最大值,暴力)
题意:给定一个图,让你找一个最大的子图,在这个子图中任何两点都有边相连,并且边不交叉,求这样子图中权值最大的是多少. 析:首先要知道的是,要想不交叉,那么最大的子图就是四个点,否则一定交叉,然后就暴力 ...
- UVaLive 7270 Osu! Master (统计)
题意:给定 n 个元素,有的有一个值,如果是 S 那么是单独一个,其他的是一个,求从 1 开始的递增的数量是多少. 析:那么S 是单独的,要统计上,既然是从 1 开始递增的,那么再统计 1 的数量即可 ...
- 网络子系统54_ip协议分片重组_定位ipq
//为分片确定正确的ipq结构 // 定位5元组 // 1.<id, 源ip, 目的ip, l4协议> 可通过ip报文获取 // 2.user 通过ip_defrag给出,指出重组是由谁发 ...
- 多线程访问winform控件出现异常的解决方法
一. 多线程访问winform控件出现异常的解决方法 1. 问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...
- C# 创建移动应用
打开VS2013 选择ASP.NET MVC4Web应用程序,点击[确定] 选择[移动应用程序]点击[确定],运行之后显示的效果如图
- C#类索引器的使用
索引器提供了一种可以让类被当作数组进行访问的方式.在C#中,类索引器是通过this的属性实现的.index.ToString("D2")将index转换成一个具有两个字符宽度的字符 ...