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

关于 C 语言自增自减的问题?

  •  
  •   nyse · 2019-02-06 21:26:46 +08:00 · 4398 次点击
    这是一个创建于 2112 天前的主题,其中的信息可能已经有所发展或是发生改变。
    main()
    {
        int i = 10, j=10;
        
        int a = ++i+j++;
        int b = j--;
        printf("%d ,%d\n", a, b); //显然,此处输出为 21 ,11
    }
    

    但是以下代码:

    main()
    {
        int i = 10, j=10;
        printf("%d ,%d\n", ++i+j++, j--);
        //此处在 Linux ( Debian9) 使用 GCC 
        //以及 Windows 下使用 code blocks (应该是 MinGW 的 gcc )输出是 20,10 ;
        //而在 macOS ( Mojave )下使用 gcc,输出是 21,11
    }
    

    这是为什么?我原本自己推测也应该是 21,11

    14 条回复    2019-02-13 19:52:05 +08:00
    momocraft
        1
    momocraft  
       2019-02-06 21:32:45 +08:00   ❤️ 4
    c 沒有規定多個參數被求值的順序, 對這個觀測的直接回答只能是"因爲編譯器這樣做".

    不要面向巧合編程.
    everwanna
        2
    everwanna  
       2019-02-06 21:35:38 +08:00 via iPhone   ❤️ 2
    不建议写这样的代码。coding 的成就感来自于创造性的解决现实问题,而不是和编译器 CPU 捉迷藏
    ipwx
        3
    ipwx  
       2019-02-06 21:41:34 +08:00   ❤️ 2
    如果你要准备某个考试,就按答案来。

    C/C++ 标准并没有规定这方面的内容,是为了让各个编译器有充分自主的空间去优化最终程序。

    所以不要写这样的代码。
    shintendo
        4
    shintendo  
       2019-02-06 21:43:15 +08:00   ❤️ 2
    编程不是实验科学,编程有个概念是“未定义行为”。
    https://bbs.csdn.net/topics/370153775
    inhzus
        5
    inhzus  
       2019-02-06 21:45:12 +08:00 via Android   ❤️ 1
    编译器不同,printf 的运算顺序不同,所以尽量避免写这样的代码。
    解释一下 20,10
    从右往左,j--,输出 10,j=9
    ++i+j,输出 20,最后 j++
    nyse
        6
    nyse  
    OP
       2019-02-06 21:46:42 +08:00
    @momocraft
    @everwanna
    @ipwx

    是啊,这就是考试的题目,我也不支持这样写。

    而且题目是写着按照 “ Turbo C 从右到左”,要不是你们提醒我还真不知道这句话说的是求值顺序。

    不过还真不明白,我在三个平台下都是用 GCC,居然也不一样。
    sdijeenx
        7
    sdijeenx  
       2019-02-06 21:48:03 +08:00
    对于:printf("%d ,%d\n", ++i+j++, j--);
    // MinGW 的 gcc 先计算 j--,再计算++i+j++;
    // macOS Mojave gcc 先计算++i+j++,再计算 j--。
    skinny
        8
    skinny  
       2019-02-07 09:41:17 +08:00
    这种考试题挺脑残的……特别是编译器到现在还是 Turbo C ……
    MrVito
        9
    MrVito  
       2019-02-07 10:55:02 +08:00
    看看 gcc 的版本吧
    ipwx
        10
    ipwx  
       2019-02-07 19:48:56 +08:00
    @nyse Turbo C 从右到左。。这句话好评。难得看到这么有水平的出题人了。
    jedihy
        11
    jedihy  
       2019-02-08 08:39:18 +08:00
    这样的代码不是 human readable 的
    unlighted
        12
    unlighted  
       2019-02-08 13:16:30 +08:00 via iPhone
    压栈的时候,从右往左压,后缀的增减会被保留到最后进行计算,++i+j-- 这个时候就是 11+9,j++之后因为有 j--,所以被抵消了,即为 10
    NULLSTRING
        13
    NULLSTRING  
       2019-02-13 15:02:53 +08:00
    junkman
        14
    junkman  
       2019-02-13 19:52:05 +08:00
    If you using -Wall to compile above code, you would see multiple unsequenced modifications warning.

    ```
    $ gcc -Wall foobar.c
    foobar.c:6:29: warning: multiple unsequenced modifications to 'j' [-Wunsequenced]
    printf("%d ,%d\n", ++i+j++, j--);
    ^ ~~
    1 warning generated.
    ```

    In short, as @momocraft aforementioned, parameter evaluation order is unspecified, it depends on compiler implementation, i.e. it can be LR-evaluated or RL-evaluated.

    BTW, above code is extremely EVIL, as a guideline, [Don't be evil]( https://en.wikipedia.org/wiki/Don%27t_be_evil)

    see: https://stackoverflow.com/questions/34266773/language-c-compile-time-error-multiple-unsequenced-modifications-werror-wun
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3250 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 13:15 · PVG 21:15 · LAX 05:15 · JFK 08:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.