关于函数参数的调用约定
文章目录
- 1.概述
- 2.函数调用约定
- 2.1 调用约定描述
- 2.2 实例分析
- 3.总结
- 4.参考
1.概述
我们先来大概了解一下函数:
- 变量有自己的类型,数组有自己的类型,函数也有其自己的类型,比如 char * func(int a[ ],long n); 这个函数的类型就是 char * (int *,long)
- 函数我们在.h文件里面进行声明,在.c文件里面进行定义
- 函数可以被其他模块调用
本篇我们讨论的重点就是函数调用。
2.函数调用约定
2.1 调用约定描述
- 当函数被调用的时候,实参argument 会被传递给 形参parameter。同时,有返回值的函数还会把返回值返回给被调用者
- 函数的参数在本质上是与局部变量相同,都是在栈上分配空间
- 实参在传递给形参之前就已经确定
- 调用约定 规定了函数参数是如何传递到栈中以及栈的维护方式,它包含形参的传递顺序和调用栈的清理。
- 调用约定通常作用于库调用和库开发的时候:
其中我们的 c 语言默认的调用规则是 __cdecl, windows API 则是__stdcall ,当我们使用c 语言开发的动态链接库 .dll 和 静态链接库 .lib 给其他语言调用的时候,就需要指明调用规则为__stdcall.。使用__cdecl规则的堆栈是由调用者来维护,包括建立和清理。从右往左依次入栈;包含\_\_stdcall, \_\_cdecl, \_\_thiscall 方式
从左往右依次入栈;包含 \_\_pascal, \_\_fastcall 方式
2.2 实例分析
test1.c
#include "stdio.h"
int main(void)
{
char Num[] = { 1,2,3,4,5};
char *p;
p = Num;
printf("%d \t %d\r\n",*p,*p++);
return 0;
}
输出:
2 1
数组假设在内存里面存储如下:(手画的,不好看,将就一下 = ^ ^ =)
根据调用约定,函数参数按照从右往左的顺序进行入栈,那么 p 和 p++ 就是先p++入栈,然后p入栈。【*p++: 先取p指向内存首元素的值,然后p++】那么对应的栈如下:
所以出栈的顺序为先2 后 1,也就是上面的结果了。
test2.c
#include "stdio.h"
int main(void)
{
char Num[] = { 1,2,3,4,5};
char *p;
p = Num;
printf("%d \t %d\r\n",*p,*++p);
return 0;
}
输出:
2 2
这个堆栈为
所以结果为2 和 2
3.总结
- c 语言默认的参数入栈顺序为从右到左
- 调用栈由被调用者管理(建立和清除) ==> 这里说明一下,如果你是自己用汇编语言的话,就不是这样了,因为那已经不是c 语言了。
- 在多数情况下我们不用在意这个约定,但是在混合编程的时候要注意。
- 对于上面例子中的*p++ 和 *p 同时出现在一个函数的形参里面的这样的劣(原来这个字读lie)质代码不要使用。
4.参考
https://www.cnblogs.com/john-h/p/6276828.html
还没有评论,来说两句吧...