V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
northisland
V2EX  ›  问与答

惭愧,至今不太了解 ++i 和 i++ 的差别

  •  
  •   northisland · 2015-07-02 18:22:18 +08:00 · 3228 次点击
    这是一个创建于 3192 天前的主题,其中的信息可能已经有所发展或是发生改变。

    只记得学校教过,这俩一个是lvalue,一个是rvalue。

    其他的区别就不知道了,求人讲解

    21 条回复    2019-11-25 10:53:02 +08:00
    kingwrcy
        1
    kingwrcy  
       2015-07-02 18:25:23 +08:00   ❤️ 1
    +在前,先加后用
    +在后,先用后加
    Zhang
        2
    Zhang  
       2015-07-02 18:26:43 +08:00
    ++i的值等于i+1,i++的值等于i
    seki
        3
    seki  
       2015-07-02 18:29:03 +08:00
    看到这两个就感到了一种熟悉的味道,那味道名叫谭浩强
    别伸手了,上网搜“++i 和 i++ 的差别”有真相

    个人觉得代码中只用一种比较好,避免脑子抽风
    66beta
        4
    66beta  
       2015-07-02 18:56:23 +08:00
    一楼言简意赅
    zhizhuo
        5
    zhizhuo  
       2015-07-02 18:59:51 +08:00
    file1:
    int main()
    {
    int i=0;
    ++i;
    return i;
    }

    file2:
    int main()
    {
    int i=0;
    i++;
    return i;
    }

    使用clang 编译后两者diff 为空。

    所以,区别就在与一个左值一个右值,
    对于编译器而且如果开了优化,所谓的多算了一次这种扯淡的效率问题是不存在的。
    FrankFang128
        6
    FrankFang128  
       2015-07-02 19:08:08 +08:00 via Android
    偷懒带来的悲剧
    ChiangDi
        7
    ChiangDi  
       2015-07-02 19:10:17 +08:00
    历史遗留问题。
    frankzeng
        8
    frankzeng  
       2015-07-02 19:11:03 +08:00 via Android
    用i+1这种形式吧,别钻牛角尖了
    zonghua
        9
    zonghua  
       2015-07-02 19:19:12 +08:00
    @frankzeng 与i=i+1 这样的问题不懂还可以理解
    lk09364
        10
    lk09364  
       2015-07-02 19:38:20 +08:00
    @zhizhuo
    javascript:

    ```
    (function(){
     var i = 0;
     return i++; // return 0
    })();


    (function(){
     var i = 0;
     return ++i; // return 1
    })();

    ```
    dreammes
        11
    dreammes  
       2015-07-02 20:24:29 +08:00
    我都忘了 有什么区别了,。。。
    SaulLawliet
        12
    SaulLawliet  
       2015-07-02 20:31:40 +08:00
    a = i++; // a = i, i += 1
    b = ++i; // i += 1, b = i
    uleh
        13
    uleh  
       2015-07-02 20:54:38 +08:00 via iPhone
    只要你保证这个语句单独执行,就希望^_^
    uleh
        14
    uleh  
       2015-07-02 20:55:04 +08:00 via iPhone
    就“一样”…
    yongzhy
        15
    yongzhy  
       2015-07-02 21:15:45 +08:00
    一楼正解,只有用于赋值和比较的时候才能体现区别,5楼的用法没有赋值或者比较,没有区别
    yanguango
        16
    yanguango  
       2015-07-02 22:19:28 +08:00
    功能上的区别是如果++表达式作为赋值语句的右值,i++是返回加之前的值,++i是返回加之后的值,这个在一些循环里善加利用能让代码更漂亮。如果++作为单独的语句,只是用来累加,那功能上没区别,一点小区别是i++ 会创建一个临时的值,用来返回, 所以这时++i性能略好,具体可参见 C++ Primer
    ryd994
        17
    ryd994  
       2015-07-02 23:35:19 +08:00
    说实话,我从来不用
    b=a++或者b=++a

    ++a;
    b=a;
    a++;
    ryd994
        18
    ryd994  
       2015-07-02 23:36:26 +08:00
    @yanguango 然而编译器会优化掉不用的部分,参见5楼
    lichao
        19
    lichao  
       2015-07-03 05:42:57 +08:00 via iPhone
    楼主,这种问题,你有这发帖时间,自己完全可以去找到答案了
    greatghoul
        20
    greatghoul  
       2015-07-03 06:00:20 +08:00 via Android
    楼主,这种问题,你有这发帖时间,自己完全可以去找到答案了
    northisland
        21
    northisland  
    OP
       2019-11-25 10:53:02 +08:00
    自己找答案毕竟限制于自己的水平,

    和在高质量社区发帖探讨一下,对问题的理解不是一个层面,我自己结束此贴

    https://stackoverflow.com/questions/48497636/understanding-the-difference-between-i-and-i-at-the-assembly-level

    rvalue 和 lvalue,需要从汇编层面才能理解到位


    Assembly for `a++`:

    0x100000f9b <+27>: movl -0x8(%rbp), %ecx # 读 -0x8(%rbp) 进 %ecx 寄存器
    0x100000f9e <+30>: addl $0x1, %ecx # %ecx 寄存器 +1
    0x100000fa1 <+33>: movl %ecx, -0x8(%rbp) # 读%ecx 寄存器进 0x8(%rbp)

    Assembly for `b++`,是和 a++相同的

    0x100000f9b <+27>: movl -0x8(%rbp), %ecx # 读 -0x8(%rbp) 进 %ecx 寄存器
    0x100000f9e <+30>: addl $0x1, %ecx # %ecx 寄存器 +1
    0x100000fa1 <+33>: movl %ecx, -0x8(%rbp) # 读%ecx 寄存器进 0x8(%rbp)

    但是不同点在于,赋值过程

    `c = a++` ( rvalue )建立 2 个寄存器

    0x100000f54 <+36>: movl -0x8(%rbp), %eax // eax = a # 内存值建立临时寄存器 1
    0x100000f57 <+39>: movl %eax, %ecx // ecx = 1 # 寄存器 1 建立寄存器 2
    0x100000f59 <+41>: addl $0x1, %ecx // ecx = 2 # 寄存器 2 + 1
    0x100000f5c <+44>: movl %ecx, -0x8(%rbp) // a = # 寄存器 2 赋值给 a 的内存值
    0x100000f5f <+47>: movl %eax, -0x10(%rbp) // c = eax = 1 # 寄存器 1 赋值给结果内存变量

    `d = ++b;` (lvalue) 建立一个寄存器

    0x100000f62 <+50>: movl -0xc(%rbp), %eax // eax = b = 1 # 内存值建立寄存器 1
    0x100000f65 <+53>: addl $0x1, %eax // eax = 2 # 寄存器+1
    0x100000f68 <+56>: movl %eax, -0xc(%rbp) // b = eax = 2 # 寄存器赋值给内存
    0x100000f6b <+59>: movl %eax, -0x14(%rbp) // d = eax = 2 # 寄存器赋值给结果内存变量
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5350 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:01 · PVG 16:01 · LAX 01:01 · JFK 04:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.