结构体、结构体体指针作为函数返回值

函数使用结构体、结构体指针作为返回值分析

32位机,gcc编译器

使用结构体作为返回值

分析反汇编代码可知,当被调用的子函数返回值为结构体的时候,调用函数将分配一段空间用于存放返回的结构体(使用一个结构体变量接受返回值),并将这段空间的地址作为调用时的参数压栈。子程序不负责对要返回的结构体分配空间。最后返回eax中存放的是结构体空间(栈中)的地址。在子程序退出的时候,调用函数可以在自己的栈帧中访问到返回的值。

#include <stdio.h>

typedef struct {
        int a;
        int b;
}Stu;

Stu getStu(int x, int y)
{
        Stu result;
        result.a = x;
        result.b = y;
        return result;
}

int main()
{
        int a = 2, b = 3;
        Stu test = getStu(a, b);
        printf("%d %d\n", test.a, test.b);
        return 0;
}

反汇编代码如下:

080483c4 <getStu>:
 80483c4:       55                      push   %ebp
 80483c5:       89 e5                   mov    %esp,%ebp
 80483c7:       83 ec 10                sub    $0x10,%esp
 80483ca:       8b 4d 08                mov    0x8(%ebp),%ecx
 80483cd:       8b 45 0c                mov    0xc(%ebp),%eax
 80483d0:       89 45 f8                mov    %eax,-0x8(%ebp)
 80483d3:       8b 45 10                mov    0x10(%ebp),%eax
 80483d6:       89 45 fc                mov    %eax,-0x4(%ebp)
 80483d9:       8b 45 f8                mov    -0x8(%ebp),%eax
 80483dc:       8b 55 fc                mov    -0x4(%ebp),%edx
 80483df:       89 01                   mov    %eax,(%ecx)
 80483e1:       89 51 04                mov    %edx,0x4(%ecx)
 80483e4:       89 c8                   mov    %ecx,%eax
 80483e6:       c9                      leave
 80483e7:       c2 04 00                ret    $0x4

080483ea <main>:
 80483ea:       8d 4c 24 04             lea    0x4(%esp),%ecx
 80483ee:       83 e4 f0                and    $0xfffffff0,%esp
 80483f1:       ff 71 fc                pushl  -0x4(%ecx)
 80483f4:       55                      push   %ebp
 80483f5:       89 e5                   mov    %esp,%ebp
 80483f7:       51                      push   %ecx
 80483f8:       83 ec 24                sub    $0x24,%esp
 80483fb:       c7 45 f0 02 00 00 00    movl   $0x2,-0x10(%ebp)
 8048402:       c7 45 f4 03 00 00 00    movl   $0x3,-0xc(%ebp)
 8048409:       8d 45 e8                lea    -0x18(%ebp),%eax
 804840c:       8b 55 f4                mov    -0xc(%ebp),%edx
 804840f:       89 54 24 08             mov    %edx,0x8(%esp)
 8048413:       8b 55 f0                mov    -0x10(%ebp),%edx
 8048416:       89 54 24 04             mov    %edx,0x4(%esp)
 804841a:       89 04 24                mov    %eax,(%esp)
 804841d:       e8 a2 ff ff ff          call   80483c4 <getStu>
 8048422:       83 ec 04                sub    $0x4,%esp
 8048425:       8b 4d ec                mov    -0x14(%ebp),%ecx
 8048428:       8b 55 e8                mov    -0x18(%ebp),%edx
 804842b:       b8 14 85 04 08          mov    $0x8048514,%eax
 8048430:       89 4c 24 08             mov    %ecx,0x8(%esp)
 8048434:       89 54 24 04             mov    %edx,0x4(%esp)
 8048438:       89 04 24                mov    %eax,(%esp)
 804843b:       e8 b4 fe ff ff          call   80482f4 <printf@plt>
 8048440:       b8 00 00 00 00          mov    $0x0,%eax
 8048445:       8b 4d fc                mov    -0x4(%ebp),%ecx
 8048448:       c9                      leave
 8048449:       8d 61 fc                lea    -0x4(%ecx),%esp

使用结构体指针作为返回值

在反汇编代码中可以看到,子程序填充malloc在堆中生成的结构体空间,并将其地址存放在eax中返回。但是这种使用方式存在的很大问题是在子程序中使用到了malloc但是没有与之对应的free,如果在调用函数中忽视释放操作的话将会导致堆内存的泄露。当然在C++中可以使用构造函数和析构函数处理这些细节。

测试使用的C程序:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
        int a;
        int b;
}Stu;

Stu * getStu(int x, int y)
{
        Stu *pStu = malloc(sizeof(Stu));
        pStu->a = x;
        pStu->b = y;
        return pStu;
}

int main()
{
        int x = 2, y = 3;
        Stu *pStu = getStu(x, y);
        printf("%d %d\n", pStu->a, pStu->b);
        free(pStu);
        return 0;
}

反汇编部分代码如下:

08048424 <getStu>:
 8048424:       55                      push   %ebp 
 8048425:       89 e5                   mov    %esp,%ebp 
 8048427:       83 ec 28                sub    $0x28,%esp 
 804842a:       c7 04 24 08 00 00 00    movl   $0x8,(%esp)
 8048431:       e8 1e ff ff ff          call   8048354 <malloc@plt>
 8048436:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048439:       8b 45 f4                mov    -0xc(%ebp),%eax 
 804843c:       8b 55 08                mov    0x8(%ebp),%edx 
 804843f:       89 10                   mov    %edx,(%eax)
 8048441:       8b 45 f4                mov    -0xc(%ebp),%eax 
 8048444:       8b 55 0c                mov    0xc(%ebp),%edx 
 8048447:       89 50 04                mov    %edx,0x4(%eax)
 804844a:       8b 45 f4                mov    -0xc(%ebp),%eax 
 804844d:       c9                      leave 
 804844e:       c3                      ret 

0804844f <main>:
 804844f:       55                      push   %ebp 
 8048450:       89 e5                   mov    %esp,%ebp
 8048452:       83 e4 f0                and    $0xfffffff0,%esp
 8048455:       83 ec 20                sub    $0x20,%esp
 8048458:       c7 44 24 14 02 00 00    movl   $0x2,0x14(%esp)
 804845f:       00 
 8048460:       c7 44 24 18 03 00 00    movl   $0x3,0x18(%esp)
 8048467:       00 
 8048468:       8b 44 24 18             mov    0x18(%esp),%eax
 804846c:       89 44 24 04             mov    %eax,0x4(%esp)
 8048470:       8b 44 24 14             mov    0x14(%esp),%eax
 8048474:       89 04 24                mov    %eax,(%esp)
 8048477:       e8 a8 ff ff ff          call   8048424 <getStu>
 804847c:       89 44 24 1c             mov    %eax,0x1c(%esp)
 8048480:       8b 44 24 1c             mov    0x1c(%esp),%eax
 8048484:       8b 48 04                mov    0x4(%eax),%ecx
 8048487:       8b 44 24 1c             mov    0x1c(%esp),%eax
 804848b:       8b 10                   mov    (%eax),%edx
 804848d:       b8 84 85 04 08          mov    $0x8048584,%eax
 8048492:       89 4c 24 08             mov    %ecx,0x8(%esp)
 8048496:       89 54 24 04             mov    %edx,0x4(%esp)
 804849a:       89 04 24                mov    %eax,(%esp)
  • 27
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
结构体指针作为函数返回值的方法是将结构体指针作为函数的返回类型,并在函数中分配内存空间来存储结构体的数据。通过返回结构体指针,可以在调用函数的地方访问和操作结构体的成员。 在C语言中,可以使用以下步骤将结构体指针作为函数返回值: 1. 定义结构体,包含需要返回的数据成员。 2. 定义函数,将返回类型设置为结构体指针函数内部使用动态内存分配函数(如malloc)分配足够的内存空间,并将结构体数据存储在该内存中。 3. 在函数结束前,将分配的内存地址返回给调用函数。 4. 在调用函数中使用一个指针变量接收函数返回的结构体指针,并通过该指针访问和操作结构体的数据成员。 下面是一个示例代码,演示了如何将结构体指针作为函数返回值: ``` #include <stdio.h> #include <stdlib.h> typedef struct { int id; char name<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [结构体结构体指针作为函数返回值](https://blog.csdn.net/weixin_41182157/article/details/83752613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [利用指针作为函数返回值](https://blog.csdn.net/weixin_42676824/article/details/117080398)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C语言 函数 使用结构体作为返回 (可返回指针,数组或常数)](https://blog.csdn.net/guiyuyang007/article/details/97501237)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值