免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yazi0127
打印 上一主题 下一主题

[C] 请教:C语言函数的返回值类型能否为结构体? [复制链接]

论坛徽章:
0
21 [报告]
发表于 2010-01-26 21:07 |只看该作者
下面这个程序没问题吧
#include <stdio.h>

struct atomic_t {
  int val ;
} ;

struct atomic_t GetAtomic()
{
  struct atomic_t a ;
  
  a.val = 0x33 ;

  return a ;
}


int main()
{
  struct atomic_t b ;

  b = GetAtomic() ;

  return b.val>0 ? 1 : 0 ;
}


去掉截屏 , 免得flw老大不高兴.


[ 本帖最后由 老手 于 2010-1-26 22:30 编辑 ]

ret_stru.jpg (291 Bytes, 下载次数: 117)

ret_stru.jpg

论坛徽章:
0
22 [报告]
发表于 2010-01-26 21:18 |只看该作者
那就从汇编的角度看看吧:
GetAtomic proc near

var_4= dword ptr -4
arg_0= dword ptr  8

push    ebp
mov     ebp, esp
sub     esp, 10h
mov     edx, [ebp+arg_0]
mov     [ebp+var_4], 33h
mov     eax, [ebp+var_4]
mov     [edx], eax
mov     eax, edx
leave
retn    4
GetAtomic endp



public main
main proc near

var_24= dword ptr -24h
arg_0= byte ptr  4

lea     ecx, [esp+arg_0]
and     esp, 0FFFFFFF0h
push    dword ptr [ecx-4]
push    ebp
mov     ebp, esp
push    ecx
sub     esp, 18h
lea     eax, [ebp-18h]
mov     [esp+24h+var_24], eax
call    GetAtomic
sub     esp, 4
mov     eax, [ebp-18h]
mov     [ebp-8], eax
mov     eax, [ebp-8]
test    eax, eax
setnle  al
movzx   eax, al
mov     ecx, [ebp-4]
leave
lea     esp, [ecx-4]
retn
main endp


gcc 4.1.1 编译 O2优化 , 请"OneWaterloo"看看VC++是不是这样的, 我没有VC.

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
23 [报告]
发表于 2010-01-26 22:14 |只看该作者

回复 #22 老手 的帖子

我写毕业论文时, 就仔细研究过返回值类型对thunk技术的影响。
应该不会记错。

既然你这么认真, 那我就再写点玩具代码验证一下:

-------- -------- -------- return_structure.c
typedef struct {
      int x;
      int y;
} Point2D32S;

Point2D32S point2d32s(int x,int y) {
      Point2D32S result = {x,y};
      return result;
}

typedef struct {
      short x;
      short y;
} Point2D16S;

Point2D16S point2d16s(short x,short y) {
      Point2D16S result = {x,y};
      return result;
}

typedef struct {
      int val;
} atomic_t;

atomic_t atomic(int val) {
      atomic_t result = {val};
      return result;
}

-------- -------- -------- msvc6  cl /W3 /O2 /FAs /c return_structure.c /Favc6.asm

PUBLIC        _point2d32s
;        COMDAT _point2d32s
_TEXT        SEGMENT
_x$ = 8
_y$ = 12
_point2d32s PROC NEAR                                        ; COMDAT

; 7    :       Point2D32S result = {x,y};

        mov        eax, DWORD PTR _x$[esp-4]
        mov        edx, DWORD PTR _y$[esp-4]

; 8    :       return result;
; 9    : }

        ret        0
_point2d32s ENDP
_TEXT        ENDS

PUBLIC        _point2d16s
;        COMDAT _point2d16s
_TEXT        SEGMENT
_x$ = 8
_y$ = 12
_result$ = 8
_point2d16s PROC NEAR                                        ; COMDAT

; 17   :       Point2D16S result = {x,y};

        mov        ax, WORD PTR _x$[esp-4]
        mov        cx, WORD PTR _y$[esp-4]
        mov        WORD PTR _result$[esp-4], ax
        mov        WORD PTR _result$[esp-2], cx

; 18   :       return result;

        mov        eax, DWORD PTR _result$[esp-4]

; 19   : }

        ret        0
_point2d16s ENDP
_TEXT        ENDS


PUBLIC        _atomic
;        COMDAT _atomic
_TEXT        SEGMENT
_val$ = 8
_atomic        PROC NEAR                                        ; COMDAT

; 26   :       atomic_t result = {val};
; 27   :       return result;

        mov        eax, DWORD PTR _val$[esp-4]

; 28   : }

        ret        0
_atomic        ENDP
_TEXT        ENDS
END


-------- -------- -------- msvc8  cl /W3 /O2 /FAs /c return_structure.c /Favc8.asm
PUBLIC        _point2d32s
_TEXT        SEGMENT
_x$ = 8                                                        ; size = 4
_y$ = 12                                                ; size = 4
_point2d32s PROC                                        ; COMDAT

; 7    :       Point2D32S result = {x,y};

        mov        eax, DWORD PTR _x$[esp-4]
        mov        edx, DWORD PTR _y$[esp-4]

; 8    :       return result;
; 9    : }

        ret        0
_point2d32s ENDP
_TEXT        ENDS


PUBLIC        _point2d16s
; Function compile flags: /Ogtpy
;        COMDAT _point2d16s
_TEXT        SEGMENT
_result$ = 8                                                ; size = 4
_x$ = 8                                                        ; size = 2
_y$ = 12                                                ; size = 2
_point2d16s PROC                                        ; COMDAT

; 17   :       Point2D16S result = {x,y};

        mov        ax, WORD PTR _x$[esp-4]
        mov        cx, WORD PTR _y$[esp-4]
        mov        WORD PTR _result$[esp-4], ax
        mov        WORD PTR _result$[esp-2], cx

; 18   :       return result;

        mov        eax, DWORD PTR _result$[esp-4]

; 19   : }

        ret        0
_point2d16s ENDP
_TEXT        ENDS


PUBLIC        _atomic
; Function compile flags: /Ogtpy
;        COMDAT _atomic
_TEXT        SEGMENT
_val$ = 8                                                ; size = 4
_atomic        PROC                                                ; COMDAT

; 26   :       atomic_t result = {val};
; 27   :       return result;

        mov        eax, DWORD PTR _val$[esp-4]

; 28   : }

        ret        0
_atomic        ENDP
_TEXT        ENDS
END



-------- -------- -------- msvc9  cl /W3 /O2 /FAs /c return_structure.c /Favc9.asm
PUBLIC        _point2d32s
_TEXT        SEGMENT
_x$ = 8                                                        ; size = 4
_y$ = 12                                                ; size = 4
_point2d32s PROC                                        ; COMDAT

; 7    :       Point2D32S result = {x,y};

        mov        eax, DWORD PTR _x$[esp-4]
        mov        edx, DWORD PTR _y$[esp-4]

; 8    :       return result;
; 9    : }

        ret        0
_point2d32s ENDP
_TEXT        ENDS


PUBLIC        _point2d16s
; Function compile flags: /Ogtpy
;        COMDAT _point2d16s
_TEXT        SEGMENT
_result$ = 8                                                ; size = 4
_x$ = 8                                                        ; size = 2
_y$ = 12                                                ; size = 2
_point2d16s PROC                                        ; COMDAT

; 17   :       Point2D16S result = {x,y};

        mov        ax, WORD PTR _x$[esp-4]
        mov        cx, WORD PTR _y$[esp-4]
        mov        WORD PTR _result$[esp-4], ax
        mov        WORD PTR _result$[esp-2], cx

; 18   :       return result;

        mov        eax, DWORD PTR _result$[esp-4]

; 19   : }

        ret        0
_point2d16s ENDP
_TEXT        ENDS


PUBLIC        _atomic
; Function compile flags: /Ogtpy
;        COMDAT _atomic
_TEXT        SEGMENT
_val$ = 8                                                ; size = 4
_atomic        PROC                                                ; COMDAT

; 26   :       atomic_t result = {val};
; 27   :       return result;

        mov        eax, DWORD PTR _val$[esp-4]

; 28   : }

        ret        0
_atomic        ENDP
_TEXT        ENDS
END



如果你看不懂intel的汇编格式, 这里还有at &t的。

-------- -------- -------- gcc4.4.0  gcc -Wall -O2 -S return_structure.c -o gcc4.4.0.s

        .p2align 2,,3
.globl _point2d32s
        .def        _point2d32s;        .scl        2;        .type        32;        .endef
_point2d32s:
        pushl        %ebp
        movl        %esp, %ebp
        movl        8(%ebp), %eax
        movl        12(%ebp), %edx
        leave
        ret
        .p2align 2,,3
.globl _point2d16s
        .def        _point2d16s;        .scl        2;        .type        32;        .endef
_point2d16s:
        pushl        %ebp
        movl        %esp, %ebp
        movzwl        12(%ebp), %eax
        sall        $16, %eax
        movw        8(%ebp), %ax
        leave
        ret
        .p2align 2,,3
.globl _atomic
        .def        _atomic;        .scl        2;        .type        32;        .endef
_atomic:
        pushl        %ebp
        movl        %esp, %ebp
        movl        8(%ebp), %eax
        leave
        ret


-------- -------- -------- gcc3.4.5  gcc -Wall -O2 -S return_structure.c -o gcc3.4.5.s
        .p2align 4,,15
.globl _point2d32s
        .def        _point2d32s;        .scl        2;        .type        32;        .endef
_point2d32s:
        pushl        %ebp
        movl        %esp, %ebp
        movl        8(%ebp), %eax
        movl        12(%ebp), %edx
        popl        %ebp
        ret
        .p2align 4,,15
.globl _point2d16s
        .def        _point2d16s;        .scl        2;        .type        32;        .endef
_point2d16s:
        pushl        %ebp
        andl        $-65536, %eax
        movl        %esp, %ebp
        movzwl        8(%ebp), %edx
        orl        %edx, %eax
        andl        $65535, %eax
        movzwl        12(%ebp), %edx
        popl        %ebp
        sall        $16, %edx
        orl        %edx, %eax
        ret
        .p2align 4,,15
.globl _atomic
        .def        _atomic;        .scl        2;        .type        32;        .endef
_atomic:
        pushl        %ebp
        movl        %esp, %ebp
        movl        8(%ebp), %eax
        popl        %ebp
        ret



-------- -------- -------- 总结
Point2D32S 返回值在eax, edx中。
Point2D16S 返回值压缩到eax中。
atomic_t      返回值在eax中。

如果gcc加上 -fomit-frame-pointer, 应该会生成完全相同的代码。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
24 [报告]
发表于 2010-01-26 22:15 |只看该作者
最讨厌发截屏的,一看就不专业。

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
25 [报告]
发表于 2010-01-26 23:31 |只看该作者
最烦那些一上来就装X的,摆出一付自己高人一等架势的家伙。就算你再牛X,谦虚一点不行么?更何况凡是人,都有出错的可能,给别人点面子,也给自己留条后路。

struct A
{
&nbsp;&nbsp;&nbsp;&nbsp;int i;
};

struct A func()
{
&nbsp;&nbsp;&nbsp;&nbsp;struct A a;
&nbsp;&nbsp;&nbsp;&nbsp;a.i = 0;
&nbsp;&nbsp;&nbsp;&nbsp;return a;
}


编译后基本上相当于(VC编译的)

void func(struct A* p)
{
&nbsp;&nbsp;&nbsp;&nbsp;struct A a;
&nbsp;&nbsp;&nbsp;&nbsp;a.i = 0;
&nbsp;&nbsp;&nbsp;&nbsp;*p = a;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//拷贝发生在这里

}


如果是C++,搞个拷贝构造函数并在其中printf,会发现有输出。

个人认为定义为void func(struct A* p)挺好,至少不用依赖编译器去优化。

论坛徽章:
0
26 [报告]
发表于 2010-01-26 23:44 |只看该作者
原帖由 w_anthony 于 2010-1-26 23:31 发表
最烦那些一上来就装X的,摆出一付自己高人一等架势的家伙。就算你再牛X,谦虚一点不行么?更何况凡是人,都有出错的可能,给别人点面子,也给自己留条后路。

void func(struct A* p)
{
&nbsp;&nbsp;&nbsp;&nbsp;struct A a;
&nbsp;&nbsp;&nbsp;&nbsp;a.i = 0;
&nbsp;&nbsp;&nbsp;&nbsp;*p = a;        //拷贝发生在这里


}



请搞清楚再说.

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
27 [报告]
发表于 2010-01-26 23:45 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
28 [报告]
发表于 2010-01-26 23:47 |只看该作者
回复 #23 OwnWaterloo 的帖子

以你的结构,结果:

[root@Server01 struct]# cat test2.c
typedef struct {
  int x;
  int y;
} Point2D32S;

Point2D32S point2d32s(int x,int y) {
  Point2D32S result = {x,y};
  return result;
}

typedef struct {
  short x;
  short y;
} Point2D16S;

Point2D16S point2d16s(short x,short y) {
  Point2D16S result = {x,y};
  return result;
}

typedef struct {
  int val;
} atomic_t;

atomic_t atomic(int val) {
  atomic_t result = {val};
  return result;
}

int main()
{
  Point2D32S  a ;

  a = point2d32s(0x55 , 0xAA) ;

  return a.x > a.y ? 1 : 0 ;
  
}
[root@Server01 struct]# gcc -Wall -O2 -fomit-frame-pointer -S test2.c
[root@Server01 struct]#ls *.s
test2.s
[root@Server01 struct]# cat test2.s
        .file        "test2.c"
        .text
        .p2align 4,,15
.globl point2d32s
        .type        point2d32s, @function
point2d32s:
        movl        4(%esp), %eax
        movl        12(%esp), %edx
        movl        %edx, 4(%eax)
        movl        8(%esp), %edx
        movl        %edx, (%eax)
        ret        $4
        .size        point2d32s, .-point2d32s
        .p2align 4,,15
.globl point2d16s
        .type        point2d16s, @function
point2d16s:
        movl        4(%esp), %eax
        movl        12(%esp), %edx
        movw        %dx, 2(%eax)
        movl        8(%esp), %edx
        movw        %dx, (%eax)
        ret        $4
        .size        point2d16s, .-point2d16s
        .p2align 4,,15
.globl atomic
        .type        atomic, @function
atomic:
        movl        4(%esp), %eax
        movl        8(%esp), %edx
        movl        %edx, (%eax)
        ret        $4
        .size        atomic, .-atomic
        .p2align 4,,15
.globl main
        .type        main, @function
main:
        leal        4(%esp), %ecx
        andl        $-16, %esp
        pushl        -4(%ecx)
        pushl        %ecx
        subl        $20, %esp
        leal        12(%esp), %eax
        movl        %eax, (%esp)
        movl        $170, 8(%esp)
        movl        $85, 4(%esp)
        call        point2d32s
        subl        $4, %esp
        movl        12(%esp), %eax
        movl        16(%esp), %edx
        cmpl        %eax, %edx
        setl        %al
        addl        $20, %esp
        popl        %ecx
        movzbl        %al, %eax
        leal        -4(%ecx), %esp
        ret
        .size        main, .-main
        .ident        "GCC: (GNU) 4.1.1 20070105 (Red Hat 4.1.1-52)"
        .section        .note.GNU-stack,"",@progbits
[root@Server01 struct]#

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
29 [报告]
发表于 2010-01-26 23:53 |只看该作者
原帖由 w_anthony 于 2010-1-26 23:31 发表
最烦那些一上来就装X的,摆出一付自己高人一等架势的家伙。就算你再牛X,谦虚一点不行么?更何况凡是人,都有出错的可能,给别人点面子,也给自己留条后路。

struct A
{
    int i;
};

struct A func()
{
    struct A a;
    a.i = 0;
    return a;
}

编译后基本上相当于(VC编译的)

void func(struct A* p)
{
    struct A a;
    a.i = 0;
    *p = a;        //拷贝发生在这里

}


你试过没有, 你确定?
23楼的汇编代码你看没有?  哪一个函数会""内存???
上面的有vc6、8、9的汇编输出, 你说的VC又是哪个版本?


再者, 只要有一个反例,就可以证明对结构体的返回并不全是采用隐藏的指针参数
反例我已经举出, 而且是5个。
所以22楼的汇编代码我看不懂(nasm?) 也不需要看懂。


原帖由 w_anthony 于 2010-1-26 23:31 发表
个人认为定义为void func(struct A* p)挺好,至少不用依赖编译器去优化。

只能说明你够牛,  你比编译器还了解如何能够生成高效代码。
比如可以用eax返回的, 非要去写一次内存。  这一定比编译器采取的方式更优化, 不是吗?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
30 [报告]
发表于 2010-01-26 23:59 |只看该作者

回复 #28 老手 的帖子

"以我的代码"并不能证明什么。

看29楼, 只要能够举出一个没有采用隐式指针参数的反例, 就可以说明这个结论是错误的:

原帖由 老手 于 2010-1-26 18:11 发表
这跟 "OneWaterloo" 说的结构体大小没有关系 , 都是这样的.


结论是 : 并不都是这样。

上面5份代码, 全都是通过寄存器返回的, 没有内存的代码。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP