nobodybutme
V2EX  ›  问与答

i=3 printf("%d %d %d %d\n", i++, ++i, i++, ++i); 求结果解释

  •  
  •   nobodybutme · Jul 12, 2015 · 9281 views
    This topic created in 4139 days ago, the information mentioned may be changed or developed.
    int i=3, j = 3, z = 3;
    printf("%d %d %d %d\n", i++, ++i, i++, ++i);
    printf("%d %d %d %d\n", j++, ++j, ++j, ++j);
    printf("%d %d %d\n", ++z, ++z, ++z);

    结果为:
    6 7 4 7
    6 7 7 7
    6 6 6

    printf 参数从右往左压栈, 我一直以为z的输出应该是6 5 4,有人帮忙解释下么?
    Supplement 1  ·  Jul 12, 2015
    实际中肯定不会写出这种代码,只是偶然看到类似题目就自己试了一下,结果一直搞不明白。

    谢谢大家的解答!
    21 replies  •  2015-07-12 17:02:51 +08:00
    zhjits
    zhjits
    Jul 12, 2015
    1
    undefined behavior
    FrankFang128
    FrankFang128
    Jul 12, 2015 via Android❤️3
    2
    结果就是写这行代码的程序员被开除。
    然后把这行重写
    choury
    choury
    Jul 12, 2015❤️1
    3
    你学的是谭浩强的C语言吗,要是我们组有人敢写这样的代码,我非得喷死他
    nobodybutme
    nobodybutme
    OP
    Jul 12, 2015
    4
    @zhjits 我win下codeblocks和linux下gcc跑的都是这个结果。 不同编译器怎么实现的? 比如i的那个,6 7 4 7 怎么得出来的?
    onlyice
    onlyice
    Jul 12, 2015
    5
    @nobodybutme 看生成的汇编代码,就知道怎样实现了
    说实话知道了也没什么用
    chaucerling
    chaucerling
    Jul 12, 2015
    6
    ++i的优先级
    lingo233
    lingo233
    Jul 12, 2015
    7
    这一定是谭浩强C
    zhjits
    zhjits
    Jul 12, 2015
    8
    @nobodybutme Windows 下面的 codeblocks 自带一个 gcc。

    Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) 运行结果:
    3 5 5 7
    3 5 6 7
    4 5 6
    zhjits
    zhjits
    Jul 12, 2015❤️1
    9
    @nobodybutme 至于具体编译器怎么实现的可以 RTFM 或者看生成的汇编啊
    johnsmith123
    johnsmith123
    Jul 12, 2015
    10
    SB
    loveuqian
    loveuqian
    Jul 12, 2015 via iPhone
    11
    了解这段代码的含义对实际开发帮助不大
    nobodybutme
    nobodybutme
    OP
    Jul 12, 2015
    12
    @zhjits Thank you! ^_^
    101
    101
    Jul 12, 2015
    13
    我记得不同的编译器实现是不一样的,类似事例似乎在 TCPL 出现过?
    dndx
    dndx
    Jul 12, 2015
    14
    有时间干啥不好非研究这种蛋疼且毫无意义的玩意。
    18000rpm
    18000rpm
    Jul 12, 2015❤️1
    15
    你们喷完还是帮人家解决一下问题嘛
    LZ 可以参考一下这个 http://docs.linuxtone.org/ebooks/C&CPP/c/ch16s03.html
    yksoft1
    yksoft1
    Jul 12, 2015
    16
    不同编译器,不同系统,不同CRT对这个实现都可能不同,因此不要在实际开发中这么写
    XiXiLocked
    XiXiLocked
    Jul 12, 2015❤️1
    17
    这和压栈顺序在概念上是无关的(实现上相关那是另一回事
    有关的是参数的计算顺序,
    比如printf("%d %d %d\n", ++z, ++z, ++z); 补上计算过程中的临时变量,那就相当于7条无序语句
    z+=1;
    int temp1 = z;
    z+=1;
    int temp2 = z;
    z+=1;
    int temp3 = z;
    printf("%d %d %d\n", temp1, temp2, temp3);
    除了print必须最后执行,初始化temp必须在z+=1之后,并没有其他约束。所以temp1,2,3的顺序可以换,temp的初始化的时机也可以后延。要出现666只要把3条temp尽量往后挪就行。

    再说这样写并不好,虽然我觉得这不是undefined behavior,而是implementation specific behavior,因为我记得语言规范上故意不限定求值顺序是为了方便编译器优化,但不管是哪种,代码已经不受自己控制了。
    en3073
    en3073
    Jul 12, 2015
    18
    xcode的答案
    3 5 5 7
    3 5 6 7
    4 5 6
    你怎么看?
    wy315700
    wy315700
    Jul 12, 2015
    19
    函数参数是从右往左压栈,但是没有定义是哪个参数先行计算
    Tink
    Tink
    Jul 12, 2015 via iPhone
    20
    自己算的 3 5 5 7

    3 5 6 7

    4 5 6
    adadada
    adadada
    Jul 12, 2015❤️1
    21
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4218 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 63ms · UTC 08:09 · PVG 16:09 · LAX 00:09 · JFK 03:09
    ♥ Do have faith in what you're doing.