【软件开发底层知识修炼】二十五 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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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

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

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

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

【Git、GitHub、GitLab】三 Git基本命令之创建仓库并向仓库中添加文件

前两篇文章已经学会了Git的基本命令与创建仓库的命令&#xff0c;点击链接查看上一篇文章&#xff1a;【Git、GitHub、GitLab】二 Git基本命令之建立Git仓库&#xff0c;本篇文章就来创建一个有模有样的仓库。该仓库中的代码是一个显示静态页面的小工程代码。 文章目录0 本文所…

Paul Graham:撼动硅谷的人(译文)

Paul Graham&#xff1a;撼动硅谷的人&#xff08;译文&#xff09; 作者&#xff1a; 阮一峰 日期&#xff1a; 2010年12月19日 为《黑客与画家》写"译者序"&#xff0c;遇到一个棘手的问题。 "应该如何介绍Paul Graham&#xff0c;才能让中国读者了解&#xf…

【软件开发底层知识修炼】二十八 C/C++中volatile的作用

上一篇文章学习了C/C中的指针与数组的区别&#xff0c;点击链接进行查看&#xff1a;【软件开发底层知识修炼】二十七 C/C中的指针与数组是不同的本篇文章将学习volatile关键字在C/C中的作用 文章目录1 实例代码分析2 问题分析3 解决方案4 拓展&#xff1a; const和volatile4 总…

计算char,short,int,long类型变量的取值范围

源自《The C Programming Language》P28 pr2-1&#xff1a; 编写一个程序以确定分别由signed及unsigned限定的char&#xff0c;short&#xff0c;int&#xff0c;long类型变量的取值范围。 参考代码&#xff1a; main.c 1 #include <stdio.h>2 #include <limits.h>…

EtherCAT主站实时性分析

转载自&#xff1a;https://blog.csdn.net/ethercat_i7/article/details/54018036 一、实时性的意义 在主从DC同步模式下&#xff0c;主站需要以非常精准的时间发送过程数据&#xff0c;如下图所示&#xff1a; 二、实时性的关键 如下图所示&#xff0c;影响实时性的关键因素是…

VNC源码研究(一)

VNC采用RFB通信协议。RFB ("remote 帧缓存 ") 是一个远程图形用户的简单协议&#xff0c;因为它工作在帧缓存级别上&#xff0c;所以它可以应用于所有的窗口系统&#xff0c;例如&#xff1a;X 11,Windows 和 Mac 系统。 独特的计算环境。 RFB 协议可进行可靠的传输…

枚举的一些常用操作

本章将介绍以下几点&#xff1a; 1、如何把其它类型转换为枚举类型&#xff1f; 2、如何把枚举中的值添加到下拉菜单中&#xff1f; 一、如何把其它类型转换为枚举类型&#xff1f; 我们回顾一下有关字符串与数字之间的转换&#xff0c;如&#xff1a; string strValue&quo…

10个开源免费的电子商务平台(转自伯乐在线)

如今&#xff0c;人们几乎可以在网络上购买到绝大部分东西&#xff0c;从电子产品、衣服&#xff0c;到机票预订和订餐。购物已转移到互联网&#xff0c;你所做的&#xff0c;只是需要付钱。当然&#xff0c;消费者会 非常注重网站的用户体验。所以&#xff0c;一个整洁安全的平…

【Git、GitHub、GitLab】五 git中裸仓库.git下的内容

上一篇文章学习了git的文件重命名与git -log 的系列命令的使用方法。点击链接查看上一篇文章&#xff1a;【Git、GitHub、GitLab】四 Git文件重命名的简单方法以及使用git log查看版本演变历史 本篇文章学习git中&#xff0c;在没有远端服务器的情况下&#xff0c;裸仓库.git中…

【Git、GitHub、GitLab】六 GIT中commit、tree和blob三个对象之间的关系

上一篇文章学习了git裸仓库.git中的内容&#xff0c;点击查看上一篇文章&#xff1a;【Git、GitHub、GitLab】五 git中裸仓库.git下的内容 本篇文章记录学习git中commit、tree和blob三个对象之间的关系。 首先需要会使用下面的命令&#xff1a; cat 命令&#xff0c; 功能&am…

【Git、GitHub、GitLab】十 将git仓库备份到本地

上一篇文章学习记录了工作中常用的一些git命令&#xff0c;点击链接查看&#xff1a;【Git、GitHub、GitLab】九 工作中非常重要的一些git用法 文章目录1 git的传输协议2 如何将git仓库备份到本地2.1 使用哑协议备份2.2 使用智能协议备份1 git的传输协议 哑协议与智能协议的区别…