还是不太明白这两个函数的区别, 一个是调用者清空堆栈, 可变参数, 一个是被调用者清空堆栈,不可变参数不知道函数怎么运行的, 所以堆栈怎么产生也不太明白, 堆栈如何产生的
// ? 这个函数有什么堆栈
void func()
{
}// ? 这个函数堆栈又是什么样,在函数退出时,堆栈怎么办
void func()
{
int a = 0 ; // 定义了一个变量, 这个变量保存在堆栈中吗
printf("%d" , a );
}// ? 这个函数会不会有堆栈,怎么样
void func()
{
char *p = (char * ) malloc( sizeof(char)) ;
free(p);
}
// ? 这个函数有什么堆栈
void func()
{
}// ? 这个函数堆栈又是什么样,在函数退出时,堆栈怎么办
void func()
{
int a = 0 ; // 定义了一个变量, 这个变量保存在堆栈中吗
printf("%d" , a );
}// ? 这个函数会不会有堆栈,怎么样
void func()
{
char *p = (char * ) malloc( sizeof(char)) ;
free(p);
}
http://blog.csdn.net/zhoujianhei/archive/2008/03/12/2172964.aspx
如汇编代码: __asm ret 4;_cdecl 需要调用函数的对象释放栈
如汇编代码: __asm add esp, 4
__stdcall调用约定相当于16位动态库中经常使用的PASCAL调用约定。在32位的VC++5.0中PASCAL调用约定不再被支持(实际上它已被定义为__stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall调用约定。两者实质上是一致的,即函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。
_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。
2、C调用约定(即用__cdecl关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。
_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。
因此,stdcall不支持可变参数
->栈中有函数的返回地址和EBP
void func()
{
}// ? 这个函数堆栈又是什么样,在函数退出时,堆栈怎么办
->栈中有函数的返回地址、EBP和局部变量a,函数退出根据调用的方式,决定有哪个清理栈。
void func()
{
int a = 0 ; // 定义了一个变量, 这个变量保存在堆栈中吗
printf("%d" , a );
}// ? 这个函数会不会有堆栈,怎么样
-> 当然有栈里的内容是:函数的返回地址,EBP和指针p本身的地址。
void func()
{
char *p = (char * ) malloc( sizeof(char)) ;
free(p);
}
只好让调用者负责,这导致生成的EXE的文件稍大