V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dengshuang
V2EX  ›  编程

c 自增的难题,想不出头绪。

  •  
  •   dengshuang · 2018-10-11 15:45:53 +08:00 · 3165 次点击
    这是一个创建于 1995 天前的主题,其中的信息可能已经有所发展或是发生改变。
    int main(){
        int i=1,b;
        b=(i++)+(i++); //关键点
        printf("this is i %d\n",i);
        printf("this is b %d\n",b);
        return 0;
    }
    
    结果
    this is i 3
    this is b 3
    

    i 等于 3,并不难想代码中有 2 次++操作。

    b 等于 3,可能要难想一点。

    b=(i++)+(i++)先计算表达式在自增

    (i++)+(i++)=1+2=3

    第一个括号先取值得到 1,在自增。 第二个括号先取值得到 2,在自增。


    上面是后缀符号,前缀符号,我还没搞明白。

    b=(i++)+(i++);改成b=(++i)+(++i);

    结果为

    this is i 3
    this is b 6
    

    我想来想去也不应该等于 6 啊! 正常逻辑应该是等于 5 啊!先自增在计算表达式!

    后来我又改成了 b=(++i)+1+(++i);`

    结果还是等于 6.

    改成了 b=(++i)+2+(++i);` 结果等于 7;这才说的通啊。。。

    16 条回复    2018-11-18 16:42:24 +08:00
    dengshuang
        1
    dengshuang  
    OP
       2018-10-11 15:46:28 +08:00
    环境
    ```
    debian9.5 64 位
    gcc 6.3.0
    ```
    minami
        2
    minami  
       2018-10-11 15:53:42 +08:00   ❤️ 1
    编译器已经很累了,它只想老老实实做优化,不想再和谭浩强玩了,你关心过它的感受吗?没有,你只关心你的 C 语言成绩
    正经点说,研究这个没啥意义,你可以反编译看看汇编代码是什么样的。
    misaka19000
        3
    misaka19000  
       2018-10-11 16:00:14 +08:00   ❤️ 1
    第一个:
    (i++)+(i++)
    左边的值为 1,右边的值为 2,1 + 2 = 3
    第二个:
    (++i)+(++i)
    我算出来 b 是 5,不知道为什么你算得是 6
    seeker
        4
    seeker  
       2018-10-11 16:01:57 +08:00
    b=(++i)+(++i)
    从结果强行猜编译后可能是这样的:
    i = i + 1 // 计算 ++i
    i = i + 1 // 计算又一个 ++ i
    int x = i // 赋值 1
    int y = i // 赋值 2
    b = x + y //最终结果
    真实情况可以看看汇编咋回事

    PS. 没人会这样写代码
    hobochen
        5
    hobochen  
       2018-10-11 16:03:20 +08:00 via Android   ❤️ 6
    我觉得 gcc 要提供这样的功能,出现未定义行为自动格式化所有硬盘
    xiri
        6
    xiri  
       2018-10-11 16:06:22 +08:00 via Android
    刚刚运行了一下,我算出来是 b=5
    dengshuang
        7
    dengshuang  
    OP
       2018-10-11 16:07:51 +08:00
    @misaka19000 看到你的结果,我就安心了。跟编译器有关
    crab
        8
    crab  
       2018-10-11 16:09:02 +08:00
    这种看汇编吧,但别写这种和自己过不去的。知道 i++和++i 就行
    innoink
        9
    innoink  
       2018-10-11 16:10:22 +08:00 via Android
    sequence point 了解一下
    innoink
        10
    innoink  
       2018-10-11 16:11:28 +08:00 via Android   ❤️ 1
    要么不钻牛角尖
    要么去学标准做语言律师
    要么看汇编面向实际
    misaka19000
        11
    misaka19000  
       2018-10-11 16:12:39 +08:00
    @xiri #6 为什么你的头像怎么萌(*╹▽╹*)
    seeker
        12
    seeker  
       2018-10-11 16:17:41 +08:00
    b=(++i)+(++i)
    GCC 编译后是这样的,所以是 6,过程跟我猜的差不多,MSVC 和 Clang 编译出来的应该是结果为 5。楼主喜欢钻牛角尖的话可以试试,GCC 让他不要优化。
    mov DWORD PTR [rbp-20], edi
    mov DWORD PTR [rbp-4], 1
    add DWORD PTR [rbp-4], 1
    add DWORD PTR [rbp-4], 1
    mov eax, DWORD PTR [rbp-4]
    add eax, eax
    mov DWORD PTR [rbp-8], eax
    mov eax, DWORD PTR [rbp-8]
    我是用这个网站看汇编的:
    https://godbolt.org/
    xiri
        13
    xiri  
       2018-10-11 16:26:30 +08:00 via Android
    @misaka19000 #11 你的头像也很萌啊

    顺便补充一下我 #6 计算结果的环境:clang 7.0.0 (不在电脑旁,在手机上的 Termux 里算的)
    innoink
        14
    innoink  
       2018-10-11 16:29:14 +08:00 via Android
    @seeker sequence point 和优化并没有什么关系,这就是个 UB
    newtype0092
        15
    newtype0092  
       2018-10-11 16:34:46 +08:00
    这不叫难题,这叫傻逼问题。。。
    adoui
        16
    adoui  
       2018-11-18 16:42:24 +08:00
    b = (i++) + (i++);
    b = 1 + (2);
    前面的的括号中 i =1,然后+1,到第二个括号是 i = 2 了,然后 1+2 赋值给 b。++放后面是先用后加。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5255 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:37 · PVG 17:37 · LAX 02:37 · JFK 05:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.