标签: 编译器

  • x=x++;

    之前囧哥曾经写过一个日志,讨论一个问题,就是在c/c++里面这个代码的结果

    x = 1;
    x = x++;
    

    执行后,x是2。这个结论还是比较显而易见的,不过编译器到底是怎么处理这段代码的呢?
    我用 Fedora 15 自带的 gcc -S -O0 将 .c 编译成 .s 文件,来看看究竟编译器干了什么。

    int x = 13; // 为了看汇编更方便,赋值13
    x = x++;
    

    被翻译成如下的汇编代码:

    movl	$13, -4(%rbp)  ;x=13
    addl	$1, -4(%rbp) ;x++
    movl	$0, %eax
    popq	%rbp
    

    从汇编码来看,gcc 是这样理解x = x++的:

    x = x; // 被优化掉了
    x++;
    

    也就是对于 int 这种 trivial 类型,= 的优先级高于后置++。 先赋值,再做后置++。
    我们再来试几个代码:
    第一组

    int x=13;
    int y;
    y = x++;
    

    翻译结果:

    movl	$13, -4(%rbp) ;x=13
    movl	-4(%rbp), %eax ;eax=x
    movl	%eax, -8(%rbp) ;y=eax
    addl	$1, -4(%rbp) ;x++
    movl	$0, %eax
    popq	%rbp
    

    ————————————————–
    第二组

    int x=13;
    int y;
    x = y = x++;
    

    翻译结果:

    movl	$13, -4(%rbp) ;x=13
    movl	-4(%rbp), %eax ;eax=x
    movl	%eax, -8(%rbp) ;y=eax
    movl	-8(%rbp), %eax ;eax=y
    movl	%eax, -4(%rbp) ;x=y
    addl	$1, -4(%rbp) ;x++
    movl	$0, %eax
    popq	%rbp
    

    ————————————————–
    第三组

    int x=13;
    int y;
    y = ++x;
    

    翻译结果:

    movl	$13, -4(%rbp) ;x=13
    addl	$1, -4(%rbp) ;++x
    movl	-4(%rbp), %eax ;eax=x
    movl	%eax, -8(%rbp) ;y=eax
    movl	$0, %eax
    popq	%rbp
    

    ————————————————–
    从各个例子中可以看出,gcc 对于 int 这种 trivial 类型,认为 = 优先级高于后置++,低于前置++。

    赋值先于后置++,后于前置++。

    即使复杂点的例子x=((x++)+(y++)),相当于:

    x=x+y;

    x++;

    y++;