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

365手游官网 📅 2025-07-03 14:56:14 ✍️ admin 👁️ 4641 ❤️ 709
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

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

相关推荐

淘宝店铺能上多少宝贝?如何上架?
P2P 网络(Peer-to-Peer Network)
全国十大马匹交易市场 全国马匹交易市场排名 国内最大的马匹交易中心→MAIGOO生活榜