链接:https://www.nowcoder.com/questionTerminal/ed83dc07e9044d928cc2d056cd7794c2
来源:牛客网
来源:牛客网
Which of the following calling convention(s) support(s) supportvariable-length parameter(e.g. printf)?
-
cdecl
- stdcall
- pascal
- fastcall
解答:A
题目的意思是:下面的函数调用约定,那个支持参数长度可变(比如printf)
函数调用约定(calling convention)函数调用约定不仅决定了发生函数调用时函数参数的入栈顺序,还决定了是由调用者函数还是被调用函数负责清除栈中的参数,还原堆栈。函数调用约定有很多方式,除了常见的__cdecl,__fastcall和__stdcall之外,C++的编译器还支持thiscall方式,不少C/C++编译器还支持naked call方式。
1.cdecl
编译器的命令行参数是/Gd。__cdecl方式是C/C++编译器默认的函数调用约定,所有非C++成员函数和那些没有用__stdcall或__fastcall声明的函数都默认是__cdecl方式,它使用C函数调用方式,函数参数按照从右向左的顺序入栈,函数调用者负责清除栈中的参数,由于每次函数调用都要由编译器产生清除(还原)堆栈的代码,所以使用__cdecl方式编译的程序比使用__stdcall方式编译的程序要大很多,但是__cdecl调用方式是由函数调用者负责清除栈中的函数参数,所以这种方式支持可变参数,比如printf和windows的API wsprintf就是__cdecl调用方式。
下面是找到的一篇讲解调用约定的博客:函数调用约定
函数调用约定就是描述参数如何传递,堆栈由调用方还是被调用方平衡,返回值如何返回等规则。
函数调用约定的几种类型有:__stdcall, __cdecl, __fastcall, __thiscall, __nakedcall, __pascal
下面介绍几种常见的函数调用约定(以VS2010编译器为例):
(1) __cdecl调用约定
1. 参数从右向左传递,放在栈中
2. 栈平衡由调用函数来执行
3. 不定参数的函数可以使用
(2)__stdcall调用约定
1. 参数从右向左传递,放在栈中
2. 栈平衡操作由被调用函数执行
3. 不定参数的函数无法使用
(3)__fastcall调用约定
1. 最左边的两个不大于4字节的参数分别放在ecx和edx寄存器,其余参数仍然从右到左压入栈
2. 被调用方平衡栈
3. 不定参数无法使用
4) __thiscall调用约定
thiscall仅仅用于c++成员函数。this指针存放于ecx寄存器中,参数从右到左压栈,被调用方平衡栈。thiscall不是关键词不能被程序员指定。