为什么VC编译器默认要用cdecl方式code generation?

时间:2022-01-29 04:49:19
除了可变参数的函数,因为caller不知道参数个数,必须由caller完成堆栈的清楚,必须用cdecl。

普通的函数不应该都用stdcall来减小代码的尺寸吗?

为什么VC默认的是cdecl呢? 个人感觉应该默认stdcall,变参函数采用cdecl就对了。

大虾解释一下吧,谢谢!!!!!

5 个解决方案

#1


_stdcall 和 __cdecl 都属于调用方式 一般我们在声明函数时都没有显示的说明调用方式,因为不同语言都有不同的默认调用方式 能否实现变参等,而_stdcall主调函数压栈,被调函数弹栈,这样被调函数只能根据他的参数表进行弹栈,所以没有办法实现变参 _cdecl主调函数压栈,主调函数弹栈,压栈时已经知道有多个参数,这样可以实现变参,估计是因为这个原因,VC编译器默认要用cdecl方式吧。

另外,__stdcall调用约定用于调用Win32 API函数,而 WINAPI一般用于修饰动态链接库中导出函数
,所以写DLL中的导出函数是都必须要要加一个__stdcall来修饰,而平常的函数可以什么修饰都不用加,因为已经默认了 __cdecl

#2


以前C时代的时候函数名称是不带修饰的,所以extern的时候参数个数对应不上,都可以通过编译和链接。如果参数个数不对,但函数是cdecl的就没事,而如果是stdcall的就会堆栈不平衡。经典范例如main函数,int main(int, char**)可以,int main()、void main()也行,int main(int, char**, char**)都没事。C/C++编译器至今还是如此,也可能只是遵循以前遗留下来的这些习惯吧?

#3


这个楼主应该给C++之父发一个邮件。

#4


这个没有孰优孰劣,在不同情况下各有优劣。就像大尾数与小尾数一样,当初选择这种做法,或许是偶然,或许是某种考虑。

#5


这个是为了保持和旧的C编译器的兼容性吧。
如果要知道C为什么用__cdecl而不用__stdcall就得去问 K&R 了

#1


_stdcall 和 __cdecl 都属于调用方式 一般我们在声明函数时都没有显示的说明调用方式,因为不同语言都有不同的默认调用方式 能否实现变参等,而_stdcall主调函数压栈,被调函数弹栈,这样被调函数只能根据他的参数表进行弹栈,所以没有办法实现变参 _cdecl主调函数压栈,主调函数弹栈,压栈时已经知道有多个参数,这样可以实现变参,估计是因为这个原因,VC编译器默认要用cdecl方式吧。

另外,__stdcall调用约定用于调用Win32 API函数,而 WINAPI一般用于修饰动态链接库中导出函数
,所以写DLL中的导出函数是都必须要要加一个__stdcall来修饰,而平常的函数可以什么修饰都不用加,因为已经默认了 __cdecl

#2


以前C时代的时候函数名称是不带修饰的,所以extern的时候参数个数对应不上,都可以通过编译和链接。如果参数个数不对,但函数是cdecl的就没事,而如果是stdcall的就会堆栈不平衡。经典范例如main函数,int main(int, char**)可以,int main()、void main()也行,int main(int, char**, char**)都没事。C/C++编译器至今还是如此,也可能只是遵循以前遗留下来的这些习惯吧?

#3


这个楼主应该给C++之父发一个邮件。

#4


这个没有孰优孰劣,在不同情况下各有优劣。就像大尾数与小尾数一样,当初选择这种做法,或许是偶然,或许是某种考虑。

#5


这个是为了保持和旧的C编译器的兼容性吧。
如果要知道C为什么用__cdecl而不用__stdcall就得去问 K&R 了