C3

c 函数返回值的陷阱

This project is maintained by wangfakang

简单解析c语言的一个坑:

先看看下面代码的输出结果:

#include <stdio.h>

#include <stdio.h>

int funx()
{
    int a = 9;
    int b = 7;
    int c = 0;

    c = a + b;
}


int main()
{
    int c = funx();

    printf("%d\n", c);

}

结果是16,对就是16.而且这个数字不是随机的。如果你知道了原因就不用再往下看了。

下面就来分析一下: 其实这个16就是a+b的值,那么问什么么恩?下面就来看看相应的汇编:

        .file   "re.c"
        .text
.globl funx
        .type   funx, @function
funx:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $9, -12(%rbp)    //把立即数9放到寄存器相对偏移量12的位置[即a的地址里面]
        movl    $7, -8(%rbp)     //把立即数7放到寄存器相对偏移量8的位置[即b的地址里面]
        movl    $0, -4(%rbp)     //把立即数0放到寄存器相对偏移量4的位置[即c的地址里面]
        movl    -8(%rbp), %eax   //把b的值取出来放到eax中
        movl    -12(%rbp), %edx  //把a的值取出来放到edx中
        leal    (%rdx,%rax), %eax //把rdx加上rax的值放到eax中
        movl    %eax, -4(%rbp)    //把eax的值给c  最终eax就是a+b等于16
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   funx, .-funx
        .section        .rodata
.LC0:
        .string "%d\n"
        .text
.globl main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $0, %eax
        call    funx     //调用funx函数
        movl    %eax, -4(%rbp)  //这个eax就是函数funx的返回值给c
        movl    $.LC0, %eax
        movl    -4(%rbp), %edx
        movl    %edx, %esi
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)"
        .section        .note.GNU-stack,"",@progbits

上面的汇编代码的第13到19行就是该问题的关键。还有就是第42到43行。
简单的看了上面汇编代码的解析,应该就知道原因了。
其实在c语言中函数的返回值是放在eax寄存器中的。[当然有的64位的也会把高32位放在edx, 低32位放在eax中]。

虽然上面的c语言代码写的很不规范,一眼就看出来不对,但是有时候一个函数的逻辑比较返回值比较多 而有的时候就会由于逻辑的问题最终一种情况没有return的逻辑。而调用者又使用该返回值来做后面的判 断是很容易出问题的。

Communite

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

Thx

Author