C++中的调用约定和名称修饰

1. 基本概念

调用约定

调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用而建立的一种协议。这种协议规定了该语言的函数中的参数传送方式、参数是否可变和由谁来处理堆栈等问题。不同的语言定义了不同的调用约定。

名称修饰

在C++中,为了允许操作符重载和函数重载,C++编译器往往按照某种规则改写每一个入口点的符号名,以便允许同一个名字(具有不同的参数类型或者是不同的作用域)有多个用法,而不会打破现有的基于C的链接器。这项技术通常被称为名称改编(Name Mangling)或者名称修饰(Name Decoration)。许多C++编译器厂商选择了自己的名称修饰方案。

2. 调用约定

2.1 __cdecl

C/C++和MFC程序默认使用的调用方式,参数个数可变,由函数调用者清栈(定义部分不知道参数数量,故无法处理)

2.2 __stdcall

用于调用Win32 API函数。参数个数固定,函数在返回前清空传递参数的堆栈。

2.3 __fastcall

用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于4个字节的参数分别放在ECXEDX寄存器,其余的参数仍旧自右向左压栈传递,被调用函数在返回前清理传递参数的堆栈。

关键字 __cdecl__stdcall__fastcall 可以直接加在要输出的函数前,也可以在编译器的命令行参数设置,分别对应为 /Gd/Gz/Gr。缺省状态为 /Gd,即 __cdecl

3. 名称修饰

名称修饰是C++编译器对函数名称的编码规则,不同的编译器有着不同的实现。

大体形式:函数名+参数类型+特定修饰符

4. extern关键字

extern 可以置于函数或变量前,以标示函数或变量的定义的在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外,extern也可以用来进行链接指定。即extern有两个作用:

  1. "C"一起连用时,如 extern "C" void fun(int a, int b);,告诉编译器在编译fun函数名时按照C的规则去翻译相应的函数名,而不使用C++的名称修饰。
  2. extern不与"C"在一起修饰变量或函数时,如在头文件中:extern int g_int,它的左右就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块或者其他模块中使用。**它是一个声明不是定义!**举栗:B模块(编译单元)要是引用A模块(编译单元)中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,会在链接时从模块A生成的目标代码中找到此函数。这种情况下,可以不用包含头文件直接用extern声明代替。
    为了防止重复定义,只在头文件中提供声明。引用一句话:只在头文件中做声明,真理总是这么简单。

4.1 extern 和 static

(1) extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量;
(2) static 表示静态的变量,分配内存的时候,存储在静态区,不存储在栈上面。

static的作用域是内部连接的关系。差别体现在:

  1. staticextern水火不容,二者不能同时修饰同一变量。
  2. static修饰的全局变量声明和定义同时进行。
  3. static修饰全局变量的作用域只能是本身的编译单元,对其他编译单元不可见。

举栗:

    // (1) test1.h:
    #ifndef TEST1H
    #define TEST1H
    static char g_str[] = "123456";		// 全局静态
    void fun1();
    #endif

    // (2) test1.cpp:
    #include "test1.h"
    void fun1()  {   cout << g_str << endl;  }
    // (3) test2.cpp
    #include "test1.h"
    void fun2()  {   cout << g_str << endl;  }

以上的两个编译单元(test1.cpp, test2.cpp),分别引用了test1.h,根据static的作用域,会在两个编译单元中分别生成变量g_str,虽然内容相同,但物理地址不同。凡事总有例外,上边的例子中,由于两个模块对变量g_str都未进行修改,所以编译器优化会将两个编译模块中的变量指向同一内存地址。一旦有一个模块对变量进行了修改,则该优化失效。
原则:一般在定义static全局变量时,都把它放在原文件中而不是头文件

4.2 extern 和 const

const 可以与 extern 连用来声明该常量可以作用于其他编译模块中。

https://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试
应支付0元
点击重新获取
扫码支付

支付成功即可阅读