V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
igboy
V2EX  ›  C

int a = 0; a = (++a) + (++a) + (++a) + (++a);为什么 a 最终等于 11

  •  
  •   igboy · Feb 9, 2015 · 4149 views
    This topic created in 4107 days ago, the information mentioned may be changed or developed.
    int a = 0; 
    a = (++a) + (++a) + (++a) + (++a);
    printf("%d\n", a);
    

    gcc version: 4.9.2

    不太懂为什么 a 会等于 11?能分析一下吗?

    68 replies    2015-02-10 20:02:20 +08:00
    skybr
        1
    skybr  
       Feb 9, 2015   ❤️ 9
    别分析了, 写出这种代码的都被打死了.
    scusjs
        2
    scusjs  
       Feb 9, 2015   ❤️ 1
    看看汇编就知道了。。会各种坑爹的优化啥的。ps. 这种代码纯属蛋疼
    igboy
        3
    igboy  
    OP
       Feb 9, 2015
    @skybr 程序肯定是不会用这种代码的,但是我只是想知道为什么啊
    skybr
        4
    skybr  
       Feb 9, 2015   ❤️ 1
    @igboy 没为什么, 看编译器怎么实现, 比如llvm就直接编译报错.
    zkd8907
        5
    zkd8907  
       Feb 9, 2015   ❤️ 2
    分析的结果就是如果我们的团队里有人写这种代码直接Failed Code Review。。
    46fo
        6
    46fo  
       Feb 9, 2015   ❤️ 1
    谁吃饱了 写这样的代码
    Do
        7
    Do  
       Feb 9, 2015   ❤️ 1
    这代码应该是体育老师教的
    Sharuru
        8
    Sharuru  
       Feb 9, 2015   ❤️ 1
    看汇编代码+1
    编译器实现+1
    Po 主可以搜索有关 C语言和自增运算的相关文章,简单来说结果完全是看编译器是怎么实现的。
    LMkillme
        9
    LMkillme  
       Feb 9, 2015   ❤️ 6
    我特想知道,开这种题目先河的是不是谭浩强?
    vzch
        10
    vzch  
       Feb 9, 2015   ❤️ 1
    @LMkillme 咱记得绿色封面第三版是有这类题的
    txx
        11
    txx  
       Feb 9, 2015 via iPhone   ❤️ 2
    这种题 不同编译器 结果不同 不同参数 结果不同
    disonlee
        12
    disonlee  
       Feb 9, 2015   ❤️ 1
    同楼上,编译器不同,结果不同的。写这代码明显是小白装大神。
    hjc4869
        13
    hjc4869  
       Feb 9, 2015   ❤️ 1
    楼主,VC2013和C#里这个结果都是16。各自都有各自的解释,这种代码出现在现实生活中就是一个字:死。
    igboy
        14
    igboy  
    OP
       Feb 9, 2015
    @skybr
    @scusjs
    @zkd8907
    @xdeng
    @Do
    @Sharuru
    @LMkillme
    @vzch
    @txx
    @disonlee
    感谢诸位,直接去反汇编,看汇编代码了
    vibbow
        15
    vibbow  
       Feb 9, 2015
    PHP给的结果是 10
    spacewander
        16
    spacewander  
       Feb 10, 2015
    不如我们试试看,不同的编译器/编程语言会得出一共多少种答案?;)
    LMkillme
        17
    LMkillme  
       Feb 10, 2015
    @spacewander 编译器还那么多版本呢。。。要不都测一遍?我支持你~
    adjusted
        18
    adjusted  
       Feb 10, 2015
    这种还是要做过编译器的专业人士来解释
    acros
        19
    acros  
       Feb 10, 2015
    两点明白了就好:
    前置自增运算符的特点,
    “+”运算符的结合方向 (这个好像不同编译器表现不一样?)
    jsq2627
        20
    jsq2627  
       Feb 10, 2015
    BGLL
        21
    BGLL  
       Feb 10, 2015 via Android
    任意两个顺序点之间的副作用的发都是未定义的.
    这是未定义行为,a=a++都是未定义行为,是错误的……
    ostholz
        22
    ostholz  
       Feb 10, 2015
    llvm 3.5 编译出来的结果是 10
    swift 结果也是 10
    yellowV2ex
        23
    yellowV2ex  
       Feb 10, 2015
    口算应该是 10 啊
    BGLL
        24
    BGLL  
       Feb 10, 2015 via Android
    这个编译器应该会有等于
    16(4+4+4+4)

    11(2+2+3+4)
    两种结果
    geeti
        25
    geeti  
       Feb 10, 2015
    谭浩强的书看多了就爱思考这种问题
    BGLL
        26
    BGLL  
       Feb 10, 2015 via Android
    我说的是 c\c++
    第一步:(++a) + (++a)编译器会的当成
    ++a;(a==1
    ++a;(a==2
    a+a;表达式值==2+2==4
    后面就是4+ (++a),楼主应该懂了

    这种式子是未定义行为是错误的,要是有题目出这种东西,使劲喷
    BGLL
        27
    BGLL  
       Feb 10, 2015 via Android
    ++a;(a==1
    ++a;(a==2
    a+a;表达式值==2+2==4(a=2
    4+ (++a)==4+3==7(a=3
    7+(++a)==7+4==11

    -
    ++a;
    ++a;
    ++a;
    ++a;
    a+a+a+a==16;
    zsj950618
        28
    zsj950618  
       Feb 10, 2015
    这应该是编译原理的作业吧。。。
    xfwduke
        29
    xfwduke  
       Feb 10, 2015
    movl $0, 28(%esp)
    addl $1, 28(%esp)
    addl $1, 28(%esp)
    movl 28(%esp), %eax
    leal (%eax,%eax), %edx
    addl $1, 28(%esp)
    movl 28(%esp), %eax
    addl %edx, %eax
    addl $1, 28(%esp)
    addl %eax, 28(%esp)
    movl 28(%esp), %eax
    movl %eax, 4(%esp)
    movl $.LC0, (%esp)
    call printf

    直接看这个最明了了
    msg7086
        30
    msg7086  
       Feb 10, 2015
    语句是非法的,搞懂了也没意义。
    ispinfx
        31
    ispinfx  
       Feb 10, 2015 via iPhone
    No zuo no die why you try!
    invite
        32
    invite  
       Feb 10, 2015
    因为规定好了。
    chrishine
        33
    chrishine  
       Feb 10, 2015
    很多人默默的B了就行了.
    楼主这种的, 要给5个铜币.
    yuankui
        34
    yuankui  
       Feb 10, 2015
    这种问题好无聊...
    quericy
        35
    quericy  
       Feb 10, 2015
    这种问题,也就谭++和应试教育喜欢出~~~~
    singer
        36
    singer  
    PRO
       Feb 10, 2015 via iPhone
    幸好学的时候,老师说谭浩强的太傻逼,直接换其他书上了。搞得我们全班比其他平行班C语言牛逼好多。只能说别学太死了。。。。能编程,这项目,就好了,不要去纠结没意义的题目啊。
    loveuqian
        37
    loveuqian  
       Feb 10, 2015
    <script type="text/javascript">
    var a = 0;
    a = (++a) + (++a) + (++a) + (++a);
    document.write(a)
    </script>

    答案是10喔
    jasonding
        38
    jasonding  
       Feb 10, 2015
    研究了下,JAVA这个题的答案是10。
    a=(++a) ;
    此时a=1
    a=(++a)+(++a) : a=1 + (++1)
    此时打印结果为3;
    a=(++a)+(++a) +(++a) : a=1 + (++1) +(++(1 + (++1)))
    此时打印结果为6;
    a=(++a)+(++a) +(++a)+(++a) : a=1 + (++1) +(++(1 + (++1)))+(++(1 + (++1) +(++(1 + (++1)))))
    此时打印结果为10。
    但是11就不知道怎么来的了
    jasonding
        39
    jasonding  
       Feb 10, 2015
    打印结果为10那一行写错了,cao
    a=(++a)+(++a) +(++a)+(++a) : a=1 + (++1) +(++(1 + (++1)))+(++(++(1 + (++1)))
    这样才是对的
    robertlyc
        40
    robertlyc  
       Feb 10, 2015
    没啥 为什么
    编译器就是这么做的 而且各家编译器还不同

    不需要理解 除非你未来工作是写/优化编译器
    frankzeng
        41
    frankzeng  
       Feb 10, 2015
    各位别不服气,去大公司应聘,笔试不就考这些吗
    Narcissu5
        42
    Narcissu5  
       Feb 10, 2015
    我记得C语言对这种带副作用的表达式的求值和传值顺序是未定义的

    so,出现什么结果都有可能,就不要深究啦
    itsasony
        43
    itsasony  
       Feb 10, 2015
    @jasonding
    1+2+3+4
    Dongdong36
        44
    Dongdong36  
       Feb 10, 2015
    不需要知道为什么,因为没人会写这种代码,如果想知道原理,就拆分开,一点点试验,分析编译器的处理顺序,不同的编译器对于未定义的操作处理方法是不同的,曾经就遇到过gcc和VS的编译结果不同。
    BGLL
        45
    BGLL  
       Feb 10, 2015
    @frankzeng 有公司敢考这玩意(认真的考),当场走,这公司没救了
    BGLL
        46
    BGLL  
       Feb 10, 2015
    @jasonding 楼主的题是C\C++,
    C\C++里第一步 a=(++a)+(++a) 可以等于3也可以等于4,看编译器,因为这是未定义行为(也就是错误写法)
    等于4的顺序是
    ++a , a =1了
    ++a,a=2了
    a+a,2+2=4了
    b821025551b
        47
    b821025551b  
       Feb 10, 2015
    这是谭浩强书上的作业吧?
    clino
        48
    clino  
       Feb 10, 2015
    为什么我用gcc编译不过呢

    t.c:3:1: warning: data definition has no type or storage class [enabled by default]
    a = (++a) + (++a) + (++a) + (++a);
    ^
    t.c:3:1: error: redefinition of ‘a’
    t.c:2:5: note: previous definition of ‘a’ was here
    int a = 0;
    ^
    t.c:3:1: error: initializer element is not constant
    a = (++a) + (++a) + (++a) + (++a);
    ^
    t.c:4:8: error: expected declaration specifiers or ‘...’ before string constant
    printf("%d\n", a);
    ^
    t.c:4:16: error: expected declaration specifiers or ‘...’ before ‘a’
    printf("%d\n", a);
    ^
    kofj
        49
    kofj  
       Feb 10, 2015
    表示Golang直接syntax error: unexpected ++
    xuyuanp
        50
    xuyuanp  
       Feb 10, 2015
    谭浩强教的
    rushcheyo
        51
    rushcheyo  
       Feb 10, 2015
    @vzch 伪 vczh 是不是很好玩?
    frankzeng
        52
    frankzeng  
       Feb 10, 2015
    @BGLL 虽然不是这题,但也差不多啊

    int a = 4;
    (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
    a = ?
    说实在的,在程序中用这种奇技淫巧,保证不打死他
    ceclinux
        53
    ceclinux  
       Feb 10, 2015
    以前觉得懂这个很牛逼

    现在看这种无聊的代码就想吐
    msg7086
        54
    msg7086  
       Feb 10, 2015
    @frankzeng 4个语句的结果都是undefined。
    robertlyc
        55
    robertlyc  
       Feb 10, 2015
    @frankzeng 说明你真的没去过大公司
    josephok
        56
    josephok  
       Feb 10, 2015
    undefined
    icanfork
        57
    icanfork  
       Feb 10, 2015
    哈哈,楼主被喷的,,连谭浩强也跟着躺枪了。。
    BGLL
        58
    BGLL  
       Feb 10, 2015
    @frankzeng
    这已经不是奇巧淫技了,是错误写法了,如果有题目是要指出这个是错误的还可以理解。
    要求值那肯定是出题人自己连 C\C++ 的顺序点、副作用是什么都不知道。
    本身就是错的语句,考什么?考想象力?这题4个语句都是未定义语句,可以让a等于任何整数值,完全取决于编译器作者心情。
    fannas
        59
    fannas  
       Feb 10, 2015 via Android
    @谭浩强
    b821025551b
        60
    b821025551b  
       Feb 10, 2015   ❤️ 1
    @belin520 作为一个曾经的全日制本科生,可以告诉你这道题就是在谭浩强的书上出来的,我还清楚的记得当时用java和c运行出两种结果,屁颠颠地去问个老教授,得到的回复是java就得10,C就得11,没有为什么;再之后用vc和devC又出了两种结果,再然后我那门课挂掉了。。。
    hooluupog
        61
    hooluupog  
       Feb 10, 2015
    Go直接报错~~
    onemoo
        62
    onemoo  
       Feb 10, 2015
    楼上很多人都说了,这个行为是undefined。
    用这几个关键字去google吧:副作用(side effect)、序列点(sequence point)

    虽然是未定义的,但如果你想知道你的gcc是用什么样的实现来得到这个结果的 ,请查看汇编:objdump -d
    Mysdes
        63
    Mysdes  
       Feb 10, 2015
    @vzch 嗯,这头像看起来和轮子小哥有点像。

    facat
        64
    facat  
       Feb 10, 2015
    标准里面没有规定++运算符的优先级,是编译器自己实现的。
    lalalanet
        65
    lalalanet  
       Feb 10, 2015
    @facat 是这样的,这是分标准表达式,每个编译器怎么处理都是随意的。这种代码写出来就是找死。
    BGLL
        66
    BGLL  
       Feb 10, 2015
    @b821025551b
    难怪,那么多人喷谭浩强....
    onlyice
        67
    onlyice  
       Feb 10, 2015
    求不问这种问题。。
    自己搜一下就知道了。。
    vwok
        68
    vwok  
       Feb 10, 2015 via Android
    对于扯这种问题的,可以把四个括号去掉让他在算算等于多少
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3022 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 154ms · UTC 08:27 · PVG 16:27 · LAX 01:27 · JFK 04:27
    ♥ Do have faith in what you're doing.