结构体作为传递和返回值的小例子
当C用struct 传递并返回值也是struct 时,编译器是如何处理的哪,下面是gcc的处理方式.
- #include <stdio.h>
- #include <stdlib.h>
- struct sa {
- int a;
- int b;
- char c;
- };
- struct sa fun1(struct sa psa)
- {
- psa.a=1;
- psa.b=99;
- psa.c='a';
- return(psa);
- }
- struct sa ss;
- int main()
- {
- struct sa k;
- struct sa ll;
- k.a=11;
- k.b=12;
- k.c='0';
- ll=fun1(k);
- printf("%d,%d,%c",k.a,k.b,k.c);
- printf("hello,world!");
- printf("%d,%d,%c",ll.a,ll.b,ll.c);
- return(0);
- }
复制代码
gcc的处理方式,注意fun1中
"movl 8(%ebp), %edx"
和
" movl %edx, %eax"
等几句.
- .file "test5.c"
- .text
- .globl fun1
- .type fun1,@function
- fun1:
- pushl %ebp
- movl %esp, %ebp
- movl 8(%ebp), %edx //ll的地址保存到edx
- movl $1, 12(%ebp) //psa.a=1
- movl $99, 16(%ebp) //psa.b=99
- movb $97, 20(%ebp) //psa.c='a'
- movl 12(%ebp), %eax //psa.a 放到eax寄存器,实际上在fun1内已经对main中ll进行赋值了.
- movl %eax, (%edx) //ll.a=psa.a
- movl 16(%ebp), %eax
- movl %eax, 4(%edx) //ll.b=psa.b
- movl 20(%ebp), %eax
- movl %eax, 8(%edx) //ll.c=psa.c
- movl %edx, %eax //eax 存放ll的地址
- leave
- ret $4
- .Lfe1:
- .size fun1,.Lfe1-fun1
- .section .rodata
- .LC0:
- .string "%d,%d,%c"
- .LC1:
- .string "hello,world!"
- .text
- .globl main
- .type main,@function
- main:
- pushl %ebp
- movl %esp, %ebp
- subl $40, %esp //本地变量空间
- andl $-16, %esp //对齐
- movl $0, %eax
- subl %eax, %esp
- movl $11, -24(%ebp) //k.a=11
- movl $12, -20(%ebp) //k.b=12
- movb $48, -16(%ebp) //k.c='0'
- leal -40(%ebp), %eax //ll的地址
- pushl -16(%ebp) //k.c
- pushl -20(%ebp) //k.b
- pushl -24(%ebp) //k.a
- pushl %eax //压入ll的地址,以便fun1能对其进行赋值
- call fun1
- addl $12, %esp
- movsbl -16(%ebp),%eax
- pushl %eax
- pushl -20(%ebp)
- pushl -24(%ebp)
- pushl $.LC0
- call printf
- addl $16, %esp
- subl $12, %esp
- pushl $.LC1
- call printf
- addl $16, %esp
- movsbl -32(%ebp),%eax
- pushl %eax
- pushl -36(%ebp)
- pushl -40(%ebp)
- pushl $.LC0
- call printf
- addl $16, %esp
- movl $0, %eax
- leave
- ret
- .Lfe2:
- .size main,.Lfe2-main
- .comm ss,12,4
- .ident "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
复制代码
[ 本帖最后由 system888net 于 2008-6-11 11:23 编辑 ]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你烦不烦的,C版说了不够,还要到这里贴
谦虚使人进步
............................................................
[ 本帖最后由 chzCPU 于 2008-6-10 00:18 编辑 ]
观点都是一样的,都是为了说明同一个问题.觉得有汇编更能说明stack和eax配合传递struct 的过程,而且感觉这个问题跟编译器有关,有必要在这个论坛也发一下.
[ 本帖最后由 system888net 于 2008-6-10 00:16 编辑 ]
很佩服你! 不但出动了马甲造势,还在C版沸沸扬扬忽悠人。
哈哈~ 你好样的。 继续~~ 兄弟看着你
别编辑你的回复呀!
着急了,是吧。继续~ 兄弟我看着你的戏
写的太不详细,你既然是在发帖子,就应该仔细说明gcc的处理方式,比如保留在什么地方,谁来清栈........
提醒的对.
已加了一些说明,不知道道能否说的清楚些.
[ 本帖最后由 system888net 于 2008-6-11 15:28 编辑 ]
也就是说明: 在gcc里, 对于结构体的返回:return(psa); 这个动作实际上是在fun1内的对ll各成员赋值的一个,而fun1内对ll的识别是靠main调用fun1时传入的ll的地址来确定的.