关于函数参数的调用约定

1.概述

我们先来大概了解一下函数:

  • 变量有自己的类型,数组有自己的类型,函数也有其自己的类型,比如 char * func(int a[ ],long n); 这个函数的类型就是 char * (int *,long)
  • 函数我们在.h文件里面进行声明,在.c文件里面进行定义
  • 函数可以被其他模块调用

本篇我们讨论的重点就是函数调用。

2.函数调用约定

2.1 调用约定描述
  • 当函数被调用的时候,实参argument 会被传递给 形参parameter。同时,有返回值的函数还会把返回值返回给被调用者
  • 函数的参数在本质上是与局部变量相同,都是在栈上分配空间
  • 实参在传递给形参之前就已经确定
  • 调用约定 规定了函数参数是如何传递到栈中以及栈的维护方式,它包含形参的传递顺序和调用栈的清理。
  • 调用约定通常作用于库调用和库开发的时候:
         从右往左依次入栈;包含__stdcall, __cdecl, __thiscall 方式
         从左往右依次入栈;包含 __pascal, __fastcall 方式

    其中我们的 c 语言默认的调用规则是 __cdecl, windows API 则是__stdcall ,当我们使用c 语言开发的动态链接库 .dll 和 静态链接库 .lib 给其他语言调用的时候,就需要指明调用规则为__stdcall.。使用__cdecl规则的堆栈是由调用者来维护,包括建立和清理。
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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来鸟 鸣间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值