C++语言学习(十二)——C++语言常见函数调用约定

C++语言学习(十二)——C++语言常见函数调用约定

一、C++语言函数调用约定简介

C /C++开发中,程序编译没有问题,但链接的时候报告函数不存在,或程序编译和链接都没有错误,但只要调用库中的函数就会出现堆栈异常等现象。上述现象出现在C和C++的代码混合使用的情况下或在C++程序中使用第三方库(非C++语言开发)的情况下,原因是函数调用约定(Calling Convention)和函数名修饰(Decorated Name)规则导致的。函数调用约定决定函数参数入栈的顺序,以及由调用者函数还是被调用函数负责清除栈中的参数等问题,而函数名修饰规则决定编译器使用何种名字修饰方式来区分不同的函数,如果函数之间的调用约定不匹配或者名字修饰不匹配就会产生以上的问题。
C++语言中的函数调用约定主要针对三个问题:
A、函数参数的入栈顺序
B、清理栈的主体(负责清理栈的主体:函数自身还是调用函数者)
C、函数名称重整
调用约定主要是指函数被调用的方式,C++语言的函数调用约定主要有stdcall,fastcall,pascal,cdecl,thiscall等约定。
在C++中,为了允许操作符重载和函数重载,C++编译器通常按照某种规则改写每一个入口点的符号名,以便允许同一个名字(具有不同的参数类型或者是不同的作用域)有多个用法,而不会打破现有的基于C的链接器。这项技术通常被称为名称改编(Name Mangling)或者名称修饰(Name Decoration)。C++编译器厂商通常选择自己的名称修饰方案。

二、C++语言常见函数调用约定

1、__stdcall

__stdcall是StandardCall的缩写,是C++的标准调用方式。__stdcall调用约定的规则如下:
A、所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。
B、被调用函数自动清理堆栈,返回值在EAX。
C、函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。

2、__cdecl

__cdecl是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法。__cdecl调用约定规则如下:
A、所有参数从右到左依次入栈
B、所有参数由调用者清除,称为手动清栈。返回值在EAX中
C、函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀?
由于由调用者清理栈,所以允许可变参数函数存在,如int sprintf(char buffer,const char format,...)。

3、__fastcall

__fastcall是快速调用约定,通过寄存器来传送参数。__fastcall调用约定的规则如下:
? A、用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送?
? B、被调用函数在返回前清理传送参数的内存栈?,返回值在EAX中
? C、函数修饰名约定:VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数?。

4、thiscall

thiscall是唯一一个不能明确指明的函数修饰符,thiscall只能用于C++类成员函数的调用,同时thiscall也是C++成员函数缺省的调用约定。由于成员函数调用还有一个this指针,因此必须特殊处理。
thiscall调用约定如下:
A、采用桟传递参数,参数从右向左入栈。如果参数个数确定,this指针通过ECX传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈。
B、对参数个数不定的,调用者清理堆栈,否则由被调函数清理堆栈
thiscall?不是关键字,程序员不能使用。

5、__pascal

__pascal?语言的调用约定,跟?__stdcall?一样,参数按照从右至左的方式入栈,函数自身清理堆栈,返回值在EAX中。VC?中已经废弃,建议使用?stdcall?代替。

原文地址:http://blog.51cto.com/9291927/2148678

时间: 2024-08-09 02:08:58

C++语言学习(十二)——C++语言常见函数调用约定的相关文章

Go语言学习(十二)面向对象编程-结构体

1.结构体的初始化方式 例如自定义一个结构体 package main import( "fmt" ) type Rect struct{ //type和struct为关键字 x,y float64 //结构体成员 widh,height float64 } func (r *Rect) Area() float64{ return r.width * r.height } func main(){ //初始结构体的几种方式: rect1 := new(Rect) rect2 := &

go语言学习十二 - 布尔表达式采用短路逻辑

package main import "fmt" func main() { //运行结果:a if true || b() { //go 的 if 判断采用短路求值,值已经确定后续的表达式不会计算也不会被调用 fmt.Println("a") } //运行结果:ba if or(true, b()) { //函数的参数必须被即时求值的 fmt.Println("a") } //运行结果:a if orfunc(true, b) { //传入函

C++语言学习(二十)——自定义内存管理

C++语言学习(二十)--自定义内存管理 一.统计类对象中成员变量的访问次数 mutable是为了突破const函数的限制而设计的,mutable修饰的成员变量将永远处于可改变的状态.mutable成员变量破坏了只读对象的内部状态,而const成员函数保证只读对象的状态不变性,因此mutable成员变量无法保证只读对象状态的不变性. #include <iostream> using namespace std; class Test { public: Test():m_count(0) {

C++语言学习(二)——C++对C语言基础语法的扩展

C++语言学习(二)--C++对C语言基础语法的扩展 C++是基于C语言扩展发展而来的面向对象的程序设计语言,本文将主要讨论C++语言基于C语言扩展的方面. 一.实用性增强 C语言中变量的定义必须在作用域开始的位置进行定义. #include <stdio.h> int main(int argc, char *argv[]) { int i;//定义变量 int j; //使用变量 for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++)

JavaScript--基于对象的脚本语言学习笔记(二)

第二部分:DOM编程 1.文档象模型(DOM)提供了访问结构化文档的一种方式,很多语言自己的DOM解析器. DOM解析器就是完成结构化文档和DOM树之间的转换关系. DOM解析器解析结构化文档:将磁盘上的结构化文档转换成内存中的DOM树 从DOM树输出结构化文档:将内存中的DOM树转换成磁盘上的结构化文档 2.DOM模型扩展了HTML元素,为几乎所有的HTML元素都新增了innerHTML属性,该属性代表该元素的"内容",即返回的某个元素的开始标签.结束标签之间的字符串内容(不包含其它

C语言学习(二)——字符串和格式化输入输出

C语言学习(二)——字符串和格式化输入输出 1.char数组类型和空字符 C没有为字符串定义专门的变量类型,而是把它存储在char数组里.数组的最后一个位置显示字符\0.这个字符就是空字符,C用它来标记字符串的结束,其ASCII码的值为(或者等同于)0.C的字符串存储时通常以这个空字符结束,该字符的存在意味着数组的单元数必须至少比要存储的字符数多1.计算机可以自己处理大多数这些细节问题(例如,scanf( )会添加'\0'使得数组内容成为C字符串). 2.strlen( )函数与sizeof运算

Go语言学习笔记(二) [变量、类型、关键字]

日期:2014年7月19日 1.Go 在语法上有着类 C 的感觉.如果你希望将两个(或更多)语句放在一行书写,它们 必须用分号分隔.一般情况下,你不需要分号. 2.Go 同其他语言不同的地方在于变量的类型在变量名的后面.例如:不是,int a,而是 a int.当定义了一个变量,它默认赋值为其类型的 null 值.这意味着,在 var a int后,a 的 值为 0.而 var s string,意味着 s 被赋值为零长度字符串,也就是 "". 3.Go语言的变量声明和赋值 在Go中使

嵌入式 Linux C语言(十二)——单链表

嵌入式 Linux C语言(十二)--单链表 一.单链表简介 1.单链表的结构 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素. 链表中的数据是以节点来表示的,每个节点由两部分构成:一个是数据域,存储数据值,另一个是指针域,存储指向下一个节点的指针. 2.单链表的节点 单链表节点的数据结构如下: typedef struct data { unsigned int id;//学生身份ID char name[LENGTH];//学生姓名 char subject[

C语言第十二讲,文件操作.

C语言第十二讲,文件操作. 一丶文件操作概述 在操作系统中,我们的文档都称为文件.操作系统也为我们提供了接口进行操作.不同语言都是使用的相同的接口,只不过封装的上层接口不一样 操作文件的步骤 打开文件->读写文件->关闭文件. 二丶文件流的概述. 文件流称为 输入流和输出流.  其实就是从内存写数据到磁盘.和从磁盘读数据到内存. 内存->磁盘  称为输出流. 输出到磁盘 磁盘->内存 称为输入流.读取到内存. 三丶文件的打开和关闭. 1.操作原型. FILE *fopen(char