zoukankan      html  css  js  c++  java
  • 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环境下是不允许的。

  • 相关阅读:
    mysql--SQL编程(关于mysql中的日期) 学习笔记2
    mysql--SQL编程(基础知识) 学习笔记1
    Geocoding java调用百度地图API v2.0 图文 实例( 解决102错误)
    java unicode转码为中文 实例
    spring hiberante 集成出现异常 java.lang.ClassNotFoundException: org.hibernate.engine.SessionFactoryImplementor
    [Spring学习笔记 7 ] Spring中的数据库支持 RowMapper,JdbcDaoSupport 和 事务处理Transaction
    [Spring学习笔记 6 ] Spring JDBC 详解
    ubuntu 连接windows远程桌面 &&rdesktop 退出全屏模式
    maven Missing artifact com.sun:tools:jar:1.5.0
    mysql 常用命令,连接数据库,查看建表语句,批量导入数据,批量更新数据,连接查询
  • 原文地址:https://www.cnblogs.com/MrListening/p/5514610.html
Copyright © 2011-2022 走看看