【软件开发底层知识修炼】二十五 ABI之函数调用约定二之函数返回值为结构体时的约定

  • 上一篇文章学习了几种函数调用约定的区别,点击链接查看上一篇文章:【软件开发底层知识修炼】二十四 ABI之函数调用约定
  • 本篇文章继续学习函数调用约定中,关于函数返回值的问题。当函数返回值为结构体时,函数返回值是如何来传给调用者的。

文章目录

  • 1 函数返回值为结构体类型
    • 1.1 函数返回值用于初始化变量
    • 1.2 函数返回值给变量赋值
  • 2 代码案例分析
  • 3 总结

1 函数返回值为结构体类型

前一篇文章我们学习了当函数的返回值是整形时,函数返回时,如何将返回值传递给调用者。是通过eax寄存器来传递的。

但是当返回值为结构体时,eax寄存器显然存不下结构体。那么该如何将返回值传递给调用者呢?

  • 函数调用时,用来接收函数返回值的结构体变量的地址需要入栈。
  • 然后被调用函数直接通过该结构体变量的地址,将返回值拷贝过去

但是有一点要注意,就是函数返回值用于初始化以及用于赋值时,这两个过程,内部的调用约定是不一样的。参考下面。

1.1 函数返回值用于初始化变量

在这里插入图片描述

上述图示的过程还是很简单的,当函数返回值作为其他变量的初始值的时候:

  • 首先将变量的地址入栈
  • 当函数返回时,将返回值拷贝到变量st的地址处即可

1.2 函数返回值给变量赋值

在这里插入图片描述

上述图示与11节内容不太一样。当函数返回值是给一个变量赋值而不是初始化的时候:

  • 首先生成一个临时的变量temp,将temp地址入栈
  • 然后当函数返回时,将返回值拷贝到这个临时变量的地址处
  • 最后再将临时变量的值赋值给st

可以看到,当函数返回值作为其他变量的初始值时只需要一次的数据拷贝,但是当函数返回值给其他变量赋值时,却是两次的数据拷贝。所以在平时的代码中,尽量都是直接将函数返回值作为初始值,而尽量不要将返回值以赋值的形式给其他变量以免造成不必要的开销。

2 代码案例分析

本来是想将实验过程写清楚的,但是想想,这个代码的调试过程还是留给读者吧。毕竟我前面写的二十几篇都是将完整的步骤写出来了,如果学会了前面gdb调试的内容那么自己调试应该不在话下。我只给出调试的思路和代码。

  • 代码:

return.c

#include <stdio.h>struct ST
{int x;int y;int z;
};struct ST f(int x, int y, int z)
{struct ST st = {0};printf("f() : &st = %p\n", &st);st.x = x;st.y = y;st.z = z;return st;
}void g()
{struct ST st = {0};printf("g() : &st = %p\n", &st);st = f(1, 2, 3);printf("g() : st.x = %d\n", st.x);printf("g() : st.y = %d\n", st.y);printf("g() : st.z = %d\n", st.z);
}void h()
{struct ST st = f(4, 5, 6);printf("h() : &st = %p\n", &st);printf("h() : st.x = %d\n", st.x);printf("h() : st.y = %d\n", st.y);printf("h() : st.z = %d\n", st.z);
}int main()
{h();g();return 0;
}

调试思路:使用gdb进行调试。在不同的函数栈帧中查看当前函数栈帧中,结构体变量的地址是否入栈或者是否有一个临时变量的地址入栈。然后通过使用gdb打断点的形式,证明最终函数返回时是将返回值拷贝到相应的地址。当然,最后最干脆的方法还是查看该程序的反汇编代码,通过阅读反汇编代码来更加清晰的认识整个函数的运行机制。

好了,这次就不写调试步骤了,有心的人可以自己调试哦~

3 总结

学会了

  • 函数返回值为结构体的时候,如何将返回值传递给调用者
  • 函数返回值作为初始化与赋值时的不同。注意效率问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

说说我最近比较迷的Criminal Minds

喜欢《犯罪心理》这部美剧很久了&#xff0c;从第四季一直到现在还在追的第六季&#xff0c;觉得集集精彩。简练而不失悬念。该片的一些情节上的特质让我总是与工作上的某些场景产生对比联想。管理模式。BAU是一个典型的家庭式的管理方式。Hotch作为大家长&#xff0c;不辞辛劳…

【软件开发底层知识修炼】二十六 ABI-应用程序二进制接口 学习总结文章目录

前面学习了ABI的知识&#xff0c;感觉受益良多。对底层与编译器有更加深刻的认识&#xff0c;为此这里将前面写过的关于ABI 的文章给列出来&#xff0c;方便学习与翻阅。 【软件开发底层知识修炼】二十一 ABI-应用程序二进制接口一【软件开发底层知识修炼】二十二 ABI-应用程序…

关于《高性能JavaScript》制表(Memoization)笔记

减少工作量是最好的性能优化技术。代码所做的事情越少&#xff0c;他的速度就越快。 书中在关于用制表优化递归的下一段代码中&#xff0c;存在问题。 function memfactorial(n){ if (!memfactorial.cache){ memfactorial.cache { "0": 1, …

CSDN-Markdown-图片设置(大小,居中)

利用markdown在编写文档时插入图片是默认靠左&#xff0c;有些时候将图片设置为居中时可以更加的美观&#xff0c;这时就需要在图片的信息前边添加如下程序 <div aligncenter>![这里写图片描述](http:...如果想将图片位于右侧&#xff0c;只需要将center改为right<di…

查询指定范围内数据记录(适用于sqlserver2005以上)

1 WITHOrderedOrders AS2 (SELECTROW_NUMBER()over(orderbyg_Id asc) asRowNumber,g_Id FROMguanxi) 3 SELECT*4 FROMOrderedOrders 5 WHERERowNumber BETWEEN50AND60;转载于:https://www.cnblogs.com/prolion/archive/2011/04/02/2003277.html

CSDN中markdown字体颜色,大小,首行缩进,居中排布

一、下面是首行缩进的两种方法 1.这里实用空格去替代缩进的字符&#xff0c;下面讲的替代包括分号 2.把输入法由半角改为全角。 两次空格之后就能够有两个汉字的缩进。 半方大的空白用&ensp;或 全方大的空白用&emsp;或 不断行的空白格用 或 示例&#xff1a; 略略略…

SQL查询中的转义字符

如果想查找“_cs”结尾的的账户select * from [user] where loginname like %_cs是不行的&#xff0c;_ 被认为是任意的字符&#xff0c;所以需要转义字符&#xff0c;有两种写法&#xff1a;select * from [user] where loginname like %[_]csselect * from [user] where logi…

【Git、GitHub、GitLab】一 Git安装与Git最小配置

Git学习开始&#xff0c;虽然只是工具。 文章目录1 Git安装2 检查Git安装版本3 Git的最小配置4 git config的其它作用域5 总结1 Git安装 下面是安装Git的的官网链接&#xff1a; Git安装 分别有Linux安装、Mac安装与Windows安装的方法。我个人安装Windows与Linux。方法在上面…

C++类构造函数初始化列表

//以前学习中很模糊的一些概念  结构函数初始化列表以一个冒号开始&#xff0c; 接着是以逗号分隔的数据成员列表&#xff0c; 上面的结构函数(运用初始化列表的结构函数)显式的初始化类的成员;而没运用初始化列表的结构函数是对类的成员赋值&#xff0c; 并没有进行显式的初…

【Git、GitHub、GitLab】二 Git基本命令之建立Git仓库

上一篇文章学习了Git的安装与最小配置&#xff1a;【Git、GitHub、GitLab】一 Git安装与Git最小配置 文章目录建立Git仓库建立Git仓库 有两种方式可以建立Git仓库&#xff1a; 用Git之前已经有项目代码&#xff0c;则使用以下两条命令建立Git仓库 $ cd 项目代码所在的文件夹 $…

poj 3273

参数搜索。 代码&#xff1a; #include<iostream> #include<fstream>using namespace std;long long n,m,mid; long long a[100001];long long solve(){long long i,j1,k0;for(i1;i<n;i){if(a[i]-a[k]>mid){j;ki-1;}}return j; }void read(){ // ifstream ci…

使用VNC软件与花生壳进行内网穿透实现在嵌入式平台中进行广域网下的远程控制

在嵌入式平台中如何实现广域网下的远程登录控制&#xff1f; 文章目录1 项目需要2 解决方案3 首先实现局域网下的VNC远程控制4 总结1 项目需要 在IM.X6q硬件平台&#xff0c;Linux4.1.15内核版本中实现在广域网下进行远程登录控制。主控机为Windows机器&#xff0c;被控机是IM…

HDU 1159 Common Subsequence

/*经典的动态规划*/#include <iostream>usingnamespacestd;charstr1[1000];charstr2[1000];intdp[1001][1001];intmain(){while(cin >>str1 >>str2){intlen1 strlen(str1);intlen2 strlen(str2);intmax -1; memset(dp,0,sizeof(dp));for(inti 0; i <len1;…

【软件开发底层知识修炼】二十七 C/C++中的指针与数组是不同的

上几篇文章学习了ABI-应用程序二进制接口&#xff1a;【软件开发底层知识修炼】二十六 ABI-应用程序二进制接口 学习总结文章目录本篇文章就指针与数组的联系与区别来学习学习 文章目录1 疑问2 指针与数组是不相等的3 解决疑问4 总结1 疑问 在具体用文字理论来说明指针与数组的…

微软MIX11大会第一天主旨以及新产品发布总结

期盼已久的MIX11终于开幕了&#xff0c;虽然没有去现场&#xff0c;但是心情还是蛮激动的。 MIX11第一天Keynote实况大概1个多小时&#xff0c;其中介绍了下一代微软浏览器&#xff0c;新工具更新以及新产品发布等&#xff0c;下面总结一下MIX11第一天的主要话题。 1. Internet…

A Star寻路相关资料汇总

A Star寻路教程&#xff08;译文&#xff09; http://www.cnblogs.com/thunder123/archive/2010/08/18/1802199.html Amits A star Page 中译文 http://dev.gameres.com/Program/Abstract/Arithmetic/AmitAStar.mht A* Pathfinding for Beginners 系列 http://www.policyalmana…