Posted on Tuesday, May 24, 2005 3:23 PM
#C & C++
|
__cdecl
|
__stdcall
|
|
C
和
C++
程序的缺省调用规范
|
为了使用这种调用规范,需要你明确的加上
__stdcall
(或
WINAPI
)文字。即
return-type
__stdcall
function-name[(argument-list)]
|
|
在被调用函数
(Callee)
返回后,由调用方
(Caller)
调整堆栈。
1.
调用方的函数调用
2.
被调用函数的执行
3.
被调用函数的结果返回
4.
调用方清除调整堆栈
|
在被调用函数
(Callee)
返回前,由被调用函数
(Callee)
调整堆栈。图示:
1.
调用方的函数调用
2.
被调用函数的执行
3.
被调用函数清除调整堆栈
4.
被调用函数的结果返回
|
|
因为每个调用的地方都需要生成一段调整堆栈的代码,所以最后生成的文件较大。
|
因为调整堆栈的代码只存在在一个地方(被调用函数的代码内),所以最后生成的文件较小。
|
|
函数的参数个数可变(就像
printf
函数一样),因为只有调用者才知道它传给被调用函数几个参数,才能在调用结束时适当地调整堆栈。
|
函数的参数个数不能是可变的。
|
|
对于定义在
C
程序文件中的输出函数,函数名会保持原样,不会被修饰。
对于定义在
C++
程序文件中的输出函数,函数名会被修饰,
MSDN
说
Underscore character (_) is prefixed to names
.
我实际测试(
VC4
和
VC6
)下来发现好像不是那么简单。
可通过在前面加上
extern
“C”
以去除函数名修饰。也可通过
.def
文件去除函数名修饰。
|
不论是
C
程序文件中的输出函数还是
C++
程序文件中的输出函数,函数名都会被修饰。
对于定义在
C
程序文件中的输出函数,
An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list.
对于定义在
C++
程序文件中的输出函数,好像更复杂,和
__cdecl
的情况类似。
好像只能通过
.def
文件去除函数名修饰。
|
|
_beginthread
需要
__cdecl
的线程函数地址
|
_beginthreadex
和
CreateThread
需要
__stdcall
的线程函数地址
|
|
两者的参数传递顺序都是从右向左。
为了让
VB
可以调用,需要用
__stdcall
调用规范来定义
C/C++
函数。请参看Microsoft KB153586 文章:How To Call C Functions That Use the _cdecl Calling Convention。
当你
LoadLibrary
一个
DLL
文件后, 把
GetProcAddress
取得的函数地址传给上面三个线程生成函数时,请务必确认实际定义在
DLL
文件的输出函数符合调用规范要求。否则,编译成
Release
版后运行,可能会破坏堆栈,程序行为不可预测。
VC
中的相关编译开关:/Gd /Gr /Gz。另外,VC6中新增加的 /GZ 编译开关可以帮你检查堆栈问题。
我也是初学者,若有不对的地方、可以补充的地方,请指教。谢谢。
|
(补充)汇编语言视点的比较文章:
Intel x86 Function-call Conventions - Assembly View
Feedback
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
7/13/2005 11:49 AM by
正好看到 参考一下
谢谢。
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
10/30/2005 3:24 PM by
很清楚啊,谢谢~
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
3/24/2006 4:32 PM by
UP
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
10/10/2006 8:22 PM by
very up
# __cdecl和__stdcall的区别
12/23/2006 7:34 AM by
函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
# 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
3/10/2007 7:13 AM by
函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
4/2/2007 10:12 PM by
真的太好了 !谢了
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
5/24/2007 5:53 PM by
very goog ,thank you !
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
5/29/2007 12:08 PM by
谢谢你的表格
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
9/17/2007 7:11 PM by
good!
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
9/26/2007 5:22 PM by
good ,xiexie a
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
9/30/2007 11:54 AM by
xiexie,
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
2/1/2008 12:51 AM by
Clear, Thanks.
# (转载)函数调用方式比较
2/13/2008 9:15 AM by
函数调用方式的比较:__cdecl,__stdcall,__fastcall,__pascal.
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
3/5/2008 6:36 PM by
谢谢,写得太好了
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
3/9/2008 9:59 AM by
还是不知道微软为什么这么做
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
11/7/2008 5:17 PM by
好
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
11/28/2008 11:36 AM by
thanks!
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
12/9/2008 6:22 PM by
8cuo
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
1/13/2009 6:28 PM by
好
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
2/28/2009 10:47 AM by
xiexie!很清楚!呵呵
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
4/9/2009 7:21 PM by
怎么这里说参数传递都一样的顺序,不是说一个从左到右,一个从右到左吗?
# re: 函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)
4/17/2009 9:08 PM by
还是不怎么清楚!!! 这里所谓的"调用者"和"被调用者" 具体指的是什么???