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

c 语言的一个问题,请各位大佬解答

  •  
  •   evilhero · 2019-12-17 05:08:40 +08:00 via Android · 4337 次点击
    这是一个创建于 1785 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有如下代码:

    int a, *b;
    a = 10;
    b = &a;
    printf("%d  %d\n", ++a, --a);
    

    加上 b= &a; 的输出:11 10
    不加上 b = &a; 的输出:10 10

    不加上的应该是`printf```的参数在进行运算前就确定了。

    现在问题是:

    为什么加上 b = &a; 后,在 printf 中的自增 /自减运算就会在 printf 确定参数前先一步执行?

    15 条回复    2019-12-17 13:24:44 +08:00
    xcstream
        1
    xcstream  
       2019-12-17 06:26:23 +08:00   ❤️ 2
    c 语言未定义的行为
    编译器不同,结果也不同
    evilhero
        2
    evilhero  
    OP
       2019-12-17 06:56:36 +08:00 via Android
    @xcstream 谢谢! c 语言万岁…太可怕了
    crc8
        3
    crc8  
       2019-12-17 09:43:30 +08:00
    gcc 下输出是 10 10 和 10 9
    azcvcza
        4
    azcvcza  
       2019-12-17 10:04:22 +08:00
    c 语言的自增在前或者在后,语义都不一样。++a 是先对 a 做递增,再输出,a++则是先输出旧 a 再更新 a 的值。
    一般还是写 a+=1 好一些
    xxdd
        5
    xxdd  
       2019-12-17 10:07:56 +08:00
    记得老早知乎的薛飞 擅长这个(狗头)
    daimiaopeng
        6
    daimiaopeng  
       2019-12-17 10:39:30 +08:00 via Android
    不同的编译器的参数入栈顺序不一样,gcc 好像从右往左
    summer20100514
        7
    summer20100514  
       2019-12-17 10:54:09 +08:00
    确实和 3 楼一样的结果,应该是编译器的优化。gcc -S 看下汇编,是不一样的
    evilhero
        8
    evilhero  
    OP
       2019-12-17 10:59:03 +08:00 via Android
    @azcvcza 正常人当然不会++a 这样子写…试卷上就会,哈哈
    tianshilei1992
        9
    tianshilei1992  
       2019-12-17 11:02:56 +08:00
    我猜是因为两次 alias analysis 的结果不同导致 instruction reorder 的结果也不同,也正如楼上所说,由于这是未定义的行为,所以表现如何就真看编译器怎么做了。
    BTW 在我的电脑上用 LLVM 两个结果都是 11 10,无论是 -O 几。
    evilhero
        10
    evilhero  
    OP
       2019-12-17 11:06:07 +08:00 via Android
    @summer20100514
    @daimiaopeng
    @xxdd
    @azcvcza
    @crc8
    @xcstream

    谢谢各位大哥了,既然是编译器问题,就不深究了,毕竟这只是考试题。
    InkStone
        11
    InkStone  
       2019-12-17 11:08:27 +08:00
    @evilhero C++ primer 上有很多*iter++的写法。其实只要你自己够熟悉,并且不要滥用,就没什么关系。
    evilhero
        12
    evilhero  
    OP
       2019-12-17 11:08:59 +08:00 via Android
    @tianshilei1992 谢谢解答,看来要多装几个编译器了
    evilhero
        13
    evilhero  
    OP
       2019-12-17 11:10:39 +08:00 via Android
    @InkStone 主要是只是&a 取了地址给 b,其他没有对 a 进行任何操作,结果竟然不一样,感觉好神奇
    anonymous256
        14
    anonymous256  
       2019-12-17 13:16:33 +08:00
    不是编译器问题! 你 google 搜这个关键词: sequence point, 就明白了.

    写出这样的代码是不应该的. 你表达式的顺序是不确定的, 行为未定义.
    https://stackoverflow.com/questions/3575350/sequence-points-in-c
    https://en.wikipedia.org/wiki/Sequence_point
    evilhero
        15
    evilhero  
    OP
       2019-12-17 13:24:44 +08:00 via Android
    @anonymous256 确实不应该这样写,但是试卷是就是这样…
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4599 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:35 · PVG 13:35 · LAX 21:35 · JFK 00:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.