您的位置:首页 > 其它

深入体会__cdecl与__stdcall

2009-09-01 18:28 211 查看
在学习C++的过程中时常碰到WINAPI或者CALLBACK这样的调用约定,每每觉得十分迷惑。究竟这些东西有什么用?不用他们又会不会有问题?经过在网上的一番搜寻以及自己动手后,整理成以下的学习笔记。
1.WINAPI与CALLBACK

其实这两者在Windows下是相同的,在windef.h中定义如下:
)
8 {
9 int count = 0, sum = 0, i = a;
10 va_list marker;
11 va_start(marker, a); //初始化
12 while(i != -1)
13 {
14 sum += i; //先加第一个参数
15 ++count;
16 i = va_arg(marker, int);//取下一个参数
17 }
18 va_end(marker);
19 return sum;
20 }
21
22 int _tmain(int argc, _TCHAR* argv[])
23 {
24 int sum = Add(1, 2, 3, -1);
25 return 0;
26 }
查看反汇编代码也可以看出清栈的操作是在Add(1, 2, 3, -1)后执行的。本来我想试试写成int __stdcall Add(int a, ...)会有什么后果的,谁知道VS在编译的时候硬是把__stdcall方式改成__cdecl方式,看来编译器也不笨啊,知道这种方式肯定会出问题,就把你的改过来了。不过这也是一个好的编译器所需要做的事情,有时候你会发现自己写的代码与实际运行会有点点差别,那可能就是编译器把自己觉得需要优化的东西优化后的结果。这时候我又想起了volatile这个关键字,它就是让编译器不要去优化的时候使用的。
6)可变参函数为什么不能用__stdcall
我觉得这个问题应该从编译时和运行时来说,因为函数的代码是在编译的时候就已经在内存中写好的,而当程序在编译的时候,可变参不能告知代码的ret n的n是多少。而add esp,n是在运行时执行的,所以知道n是多少。
4.写在后面
相对__cdecl和__stdcall还有很多约定,这里就不细说了。以前学汇编没细学,现在才发现只有从最最低层的代码才能看到程序的原貌。C++那层有时候还看不出问题,中间还有个编译器在搞鬼。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: