关于函数参数的调用约定

你的名字 2023-07-12 06:24 110阅读 0赞

文章目录

    • 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。同时,有返回值的函数还会把返回值返回给被调用者
  • 函数的参数在本质上是与局部变量相同,都是在栈上分配空间
  • 实参在传递给形参之前就已经确定
  • 调用约定 规定了函数参数是如何传递到栈中以及栈的维护方式,它包含形参的传递顺序和调用栈的清理。
  • 调用约定通常作用于库调用和库开发的时候:
    1. 从右往左依次入栈;包含\_\_stdcall, \_\_cdecl, \_\_thiscall 方式
    2. 从左往右依次入栈;包含 \_\_pascal, \_\_fastcall 方式
    其中我们的 c 语言默认的调用规则是 __cdecl, windows API 则是__stdcall ,当我们使用c 语言开发的动态链接库 .dll 和 静态链接库 .lib 给其他语言调用的时候,就需要指明调用规则为__stdcall.。使用__cdecl规则的堆栈是由调用者来维护,包括建立和清理。

2.2 实例分析

test1.c

  1. #include "stdio.h"
  2. int main(void)
  3. {
  4. char Num[] = { 1,2,3,4,5};
  5. char *p;
  6. p = Num;
  7. printf("%d \t %d\r\n",*p,*p++);
  8. return 0;
  9. }

输出:

  1. 2 1

在这里插入图片描述数组假设在内存里面存储如下:(手画的,不好看,将就一下 = ^ ^ =)

在这里插入图片描述
根据调用约定,函数参数按照从右往左的顺序进行入栈,那么 p 和 p++ 就是先p++入栈,然后p入栈。【*p++: 先取p指向内存首元素的值,然后p++】那么对应的栈如下:
在这里插入图片描述
所以出栈的顺序为先2 后 1,也就是上面的结果了。
test2.c

  1. #include "stdio.h"
  2. int main(void)
  3. {
  4. char Num[] = { 1,2,3,4,5};
  5. char *p;
  6. p = Num;
  7. printf("%d \t %d\r\n",*p,*++p);
  8. return 0;
  9. }

输出:

  1. 2 2

在这里插入图片描述
这个堆栈为
在这里插入图片描述
所以结果为2 和 2

3.总结

  • c 语言默认的参数入栈顺序为从右到左
  • 调用栈由被调用者管理(建立和清除) ==> 这里说明一下,如果你是自己用汇编语言的话,就不是这样了,因为那已经不是c 语言了。
  • 在多数情况下我们不用在意这个约定,但是在混合编程的时候要注意。
  • 对于上面例子中的*p++ 和 *p 同时出现在一个函数的形参里面的这样的劣(原来这个字读lie)质代码不要使用。

4.参考

https://www.cnblogs.com/john-h/p/6276828.html

发表评论

表情:
评论列表 (有 0 条评论,110人围观)

还没有评论,来说两句吧...

相关阅读

    相关 函数调用约定与区别

          在调用成员函数之前,必须先把参数压到栈中,然后再进入成员函数中,成员函数依次把参数从栈中取出来,在函数返回之前或返回之后,必须恢复栈的当前位置,才能保证程序的正常运