i=1,为什么 (++i)+(++i)=6?

源码

#include "stdio.h"

int main(void)
{
    int i = 1;
    printf("%d\n",(++i) +(++i));
    return 0;
}

执行

weiqifa@bsp-ubuntu1804:~/c/undif$ gcc g.c && ./a.out
6
weiqifa@bsp-ubuntu1804:~/c/undif$

为什么出现这个鬼现象?

原因很简单,C语言的法律里面没有定义这条规格,这个属于C语言的未定义行为,也就是擦边球,什么是擦边球呢?就是这些行为不是错误的行为,法律没有明确定义的,所以就是擦边球。

它的执行顺序是这样的

int i = 1;
++i ;//i = 2
++i ;//i = 3
i + i ; //输出6

反汇编看看

weiqifa@bsp-ubuntu1804:~/c/undif$ gcc -S g.c
weiqifa@bsp-ubuntu1804:~/c/undif$ cat g.s
        .file   "g.c"
        .text
        .p        .rodata
.LC0:
        .string "%d\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .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    $1, -4(%rbp)
        addl    $1, -4(%rbp)
        addl    $1, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    %eax, %eax
        movl    %eax, %esi
        leaq    .LC0(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
        .p        .note.GNU-stack,"",@progbits
weiqifa@bsp-ubuntu1804:~/c/undif$ ls

我们不用关注所有的代码,分析下面几行关键的

subq    $16, %rsp
movl    $1, -4(%rbp) //相当于 i = 1
addl    $1, -4(%rbp) //相当于 i +1
addl    $1, -4(%rbp) //相当于 i +1
movl    -4(%rbp), %eax // 把rbp寄存器传给eax寄存器
addl    %eax, %eax //相当于 i + i

看完这个代码后,应该知道为啥输出的是 6 了吧?

最后

我认为一个是编译器执行顺序的问题,反汇编无非就是搞清楚C的执行顺序,而且我认为研究这个是有意义的,不过有意义不代表可以这样写代码。

C本身是偏底层的东西,了解编译的原理和过程是非常重要的。

但是了解也不能这样瞎用,还是要遵守规则,要不然,这样导致的bug估计要害死很多人。

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

嵌入式Linux

微信扫描二维码,关注我的公众号

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值