How do C compilers implement functions that return large structures?

前端 未结 5 2012
长发绾君心
长发绾君心 2020-11-29 05:04

The return value of a function is usually stored on the stack or in a register. But for a large structure, it has to be on the stack. How much copying has to happen in a rea

5条回答
  •  悲&欢浪女
    2020-11-29 05:56

    There are many examples given, but basically

    This question does not have any definite answer. it will depend on the compiler.

    C does not specify how large structs are returned from a function.

    Here's some tests for one particular compiler, gcc 4.1.2 on x86 RHEL 5.4

    gcc trivial case, no copying

    [00:05:21 1 ~] $ gcc -O2 -S -c t.c
    [00:05:23 1 ~] $ cat t.s
            .file   "t.c"
            .text
            .p2align 4,,15
    .globl createData
            .type   createData, @function
    createData:
            pushl   %ebp
            movl    %esp, %ebp
            movl    8(%ebp), %eax
            movl    $1, 24(%eax)
            popl    %ebp
            ret     $4
            .size   createData, .-createData
            .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-46)"
            .section        .note.GNU-stack,"",@progbits
    

    gcc more realistic case , allocate on stack, memcpy to caller

    #include 
    struct Data {
        unsigned values[256];
    };
    struct Data createData()
    {
        struct Data data;
        int i;
        for(i = 0; i < 256 ; i++)
            data.values[i] = rand();
        return data;
    }
    
    [00:06:08 1 ~] $ gcc -O2 -S -c t.c
    [00:06:10 1 ~] $ cat t.s
            .file   "t.c"
            .text
            .p2align 4,,15
    .globl createData
            .type   createData, @function
    createData:
            pushl   %ebp
            movl    %esp, %ebp
            pushl   %edi
            pushl   %esi
            pushl   %ebx
            movl    $1, %ebx
            subl    $1036, %esp
            movl    8(%ebp), %edi
            leal    -1036(%ebp), %esi
            .p2align 4,,7
    .L2:
            call    rand
            movl    %eax, -4(%esi,%ebx,4)
            addl    $1, %ebx
            cmpl    $257, %ebx
            jne     .L2
            movl    %esi, 4(%esp)
            movl    %edi, (%esp)
            movl    $1024, 8(%esp)
            call    memcpy
            addl    $1036, %esp
            movl    %edi, %eax
            popl    %ebx
            popl    %esi
            popl    %edi
            popl    %ebp
            ret     $4
            .size   createData, .-createData
            .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-46)"
            .section        .note.GNU-stack,"",@progbits
    

    gcc 4.4.2### has grown a lot, and does not copy for the above non-trivial case.

            .file   "t.c"
            .text
            .p2align 4,,15
    .globl createData
            .type   createData, @function
    createData:
            pushl   %ebp
            movl    %esp, %ebp
            pushl   %edi
            pushl   %esi
            pushl   %ebx
            movl    $1, %ebx
            subl    $1036, %esp
            movl    8(%ebp), %edi
            leal    -1036(%ebp), %esi
            .p2align 4,,7
    .L2:
            call    rand
            movl    %eax, -4(%esi,%ebx,4)
            addl    $1, %ebx
            cmpl    $257, %ebx
            jne     .L2
            movl    %esi, 4(%esp)
            movl    %edi, (%esp)
            movl    $1024, 8(%esp)
            call    memcpy
            addl    $1036, %esp
            movl    %edi, %eax
            popl    %ebx
            popl    %esi
            popl    %edi
            popl    %ebp
            ret     $4
            .size   createData, .-createData
            .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-46)"
            .section        .note.GNU-stack,"",@progbits
    

    In addition, VS2008 (compiled the above as C) will reserve struct Data on the stack of createData() and do a rep movsd loop to copy it back to the caller in Debug mode, in Release mode it will move the return value of rand() (%eax) directly back to the caller

提交回复
热议问题