我们知道在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环境下是不允许的。

————————————————
原文链接:https://blog.csdn.net/mr_listening/article/details/51472184

C++函数名的修饰规则相关推荐

  1. linux c变量命名规则,C语言中变量名及函数名的命名规则与驼峰命名法

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

  2. c语言中函数名可不可以由用户命名,C语言中变量名及函数名的命名规则与驼峰命名法...

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

  3. c语言变量名、函数名的命名规则

    (1)标识符的命名要清晰.明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解--尽量采用采用英文单词或全部中文全拼表示,若出现英文单词和中文混合定义时,使用连字符" ...

  4. c语言驼峰命名法作用,C语言中变量名及函数名的命名规则与驼峰命名法

    在程序设计中,变量名.函数名.数组名等统称为标识 符.简单地说,标识符就是一个名字.除库函数的函数名由系统定义外,其余都由用户自定义.C语言规定,标识符只能由字母(a-z,A-Z).数字 (0-9). ...

  5. Linux函数名加数字,C++ 编译器的函数名修饰规则

    函数名字修饰(Decorated Name)方式 函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型.LINK程序或其他工具有时需要指定函数的 ...

  6. c, c++函数名编译符号修饰符说明

    C++ 编译器的函数名修饰规则 函数名字修饰(Decorated Name)方式 函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串.用来指明函数的定义或原型. LIN ...

  7. C/C++函数名修饰约定

    函数名字修饰(Decorated Name)方式 函数的名字修饰(Decorated Name)就是编译器在编译期间创建的一个字符串,用来指明函数的定义或原型. 正在装载数据-- LINK程序或其他工 ...

  8. 函数调用约定 and 函数名字修饰规则

    使用C/C++语言开发软件的程序员经常碰到这样的问题:有时候是程序编译没有问题,但是链接的时候总是报告函数不存在(经典的LNK2001错误),有时候是程序编译和链接都没有错误,但是只要调用库中的函数就 ...

  9. 如何通过函数名的字符串运行函数(从dll动态库谈起,使用c++)

    1.问题描述 比如现在有一个函数叫MyFunc,现在想通过函数名调用该函数,该怎么办呢? 2.概述 如果这个问题是JAVA语言,我们会很自然的想到反射来解决这个问题,但是c++中没有反射,该怎么办呢? ...

最新文章

  1. 语音信号处理_书单 | 语音研究进阶指南
  2. jittor 和pytorch的生成网络对比之aae
  3. Math对象及相关方法
  4. c++11 移动语义move semantics
  5. Python小说爬虫
  6. Java8-初识Lambda
  7. python填补缺失值数据驱动代码_python数据预处理之缺失值的各种填补方式
  8. 【LeetCode】Combination Sum(组合总和)
  9. Lazy Load Plugin for jQuery延迟加载测试成功
  10. 2019年9月23日、24日北京市出租车数据
  11. sniffer Pro4.7.5最完整安装教程
  12. matlab对数坐标的使用
  13. ckfinder的使用及了解config.xml的配置
  14. HDLC概述-iealb
  15. Borůvka算法学习小记
  16. excel文件中的多个工作表按名称排序
  17. 【敏捷4.2】相关方的沟通与协同
  18. linux 对设备不适当的ioctl操作,似乎对设备的直接操作只有ioctl函数了
  19. java+js实现展示本地文件夹下的所有图片demo
  20. 人工智能在教育行业的应用

热门文章

  1. es6 语法 (函数扩展)
  2. Web前端行业的机遇与自我规划,如果你对未来没有方向 不如看一看,或许就是一道曙光!
  3. python selenium 判断元素是否可见
  4. Maven补全之生命周期(Lifecycle)
  5. 『Balancing Act 树的重心』
  6. DB 数据同步到数据仓库的架构与实践
  7. 站长工具--IP地址库
  8. GCDAynscSocket简单使用-客户端
  9. SQL 附加数据库时出现 无法打开物理文件错误
  10. 网站页面左右_广州网站优化的技巧是什么?