zoukankan      html  css  js  c++  java
  • GCC下宏扩展后的++i

    听讨论的时候,遇到一题是关于++i*++i的——这样的讨论意义不大,却也可以一窥编译器对相关问题的处理。

    原题如下

    相关代码说明如下

    #include <stdio.h>
    #define POWER(X) X*X
    int main()
    {
    int ch = 8;
    int sum = POWER(ch++);
    sum
    = POWER(++ch);
    return 0;
    }

    如果添加printf输出,其第一个sum = 64,第二个sum = 144

    将上面的进行汇编编译得到。

    gcc -S test.c

    程序main的主要汇编代码

    main:
    pushl %ebp
    movl %esp, %ebp
    subl $
    16, %esp
    movl $
    8, -8(%ebp)
    movl -
    8(%ebp), %eax
    imull -
    8(%ebp), %eax
    movl %eax, -
    4(%ebp)
    addl $
    1, -8(%ebp)
    addl $
    1, -8(%ebp)
    addl $
    1, -8(%ebp)
    addl $
    1, -8(%ebp)
    movl -
    8(%ebp), %eax
    imull -
    8(%ebp), %eax
    movl %eax, -
    4(%ebp)
    movl $
    0, %eax
    leave
    ret

    少去进栈出栈的操作,i++*i++产生的汇编代码是

         movl -8(%ebp), %eax
    imull -
    8(%ebp), %eax
    movl %eax, -
    4(%ebp)
    addl $
    1, -8(%ebp)
    addl $
    1, -8(%ebp)

    ++i*++i产生的汇编代码是

    addl $1, -8(%ebp)
    addl $
    1, -8(%ebp)
    movl -
    8(%ebp), %eax
    imull -
    8(%ebp), %eax

    由上面的代码可以看出

    1)i++的自增操作是在整个乘法完成之后才进行的,而++i的操作则是在乘法之前进行。

    2)movl和imull总是连续出现,进行乘法的时候,左右的操作数是从同一块内存取出来的,因此计算结果肯定是完全平方数。

    找到一篇相似的文章《分析gcc下的i++与++i》gfw),在后续讨论三个i++的情况。后面还有总结,先一并摘抄过来。

    ++i*i++*++i的汇编代码为  

    movl $8, -8(%ebp)
    addl $
    1, -8(%ebp)
    movl -
    8(%ebp), %eax
    imull -
    8(%ebp), %eax
    addl $
    1, -8(%ebp)
    imull -
    8(%ebp), %eax
    movl %eax, -
    4(%ebp)
    addl $
    1, -8(%ebp)
    leave
    ret

    摘录

    分析一下上面的代码,结论就很清晰了,所有的i++操作会在整个表达式计算完后才计算,除了最左边的乘法会从同一块内存取操作数外,后续的乘法的作操作数就是直接取的上次计算的结果。

    总结一下:

    1.从左向右计算
    2.最左边的乘法从同一内存取操作数,因此肯定是完全平方数
    3.所有的i
    ++可以替换成i
    4.所有的
    ++i先计算增一,再取增一后的值
    比如计算 i++*++i*++i*i++*++i (i=3): 结果是 4×4×5×5×6=2400.


  • 相关阅读:
    Oracle的序列、视图、索引和表空间
    MySQL存储过程
    MySQL触发器
    MySQL索引和视图
    完整性约束
    Mybatis的核心对象及运行流程
    Mybatis中配置连接池
    IDEA中创建Maven工程整合Mybatis
    Idea中创建JavaWeb工程
    实现整数集合的并、交、差运算
  • 原文地址:https://www.cnblogs.com/westfly/p/2095474.html
Copyright © 2011-2022 走看看