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

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

  •  
  •   igboy · 2015-02-09 23:10:21 +08:00 · 3395 次点击
    这是一个创建于 3362 天前的主题,其中的信息可能已经有所发展或是发生改变。
    int a = 0; 
    a = (++a) + (++a) + (++a) + (++a);
    printf("%d\n", a);
    

    gcc version: 4.9.2

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

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

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

    这种式子是未定义行为是错误的,要是有题目出这种东西,使劲喷
    BGLL
        27
    BGLL  
       2015-02-10 01:05:19 +08:00 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  
       2015-02-10 01:10:36 +08:00
    这应该是编译原理的作业吧。。。
    xfwduke
        29
    xfwduke  
       2015-02-10 02:02:33 +08:00
    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  
       2015-02-10 04:04:35 +08:00
    语句是非法的,搞懂了也没意义。
    ispinfx
        31
    ispinfx  
       2015-02-10 08:17:36 +08:00 via iPhone
    No zuo no die why you try!
    invite
        32
    invite  
       2015-02-10 08:45:48 +08:00
    因为规定好了。
    chrishine
        33
    chrishine  
       2015-02-10 08:52:46 +08:00
    很多人默默的B了就行了.
    楼主这种的, 要给5个铜币.
    yuankui
        34
    yuankui  
       2015-02-10 09:09:53 +08:00
    这种问题好无聊...
    quericy
        35
    quericy  
       2015-02-10 09:12:24 +08:00
    这种问题,也就谭++和应试教育喜欢出~~~~
    singer
        36
    singer  
       2015-02-10 09:24:51 +08:00 via iPhone
    幸好学的时候,老师说谭浩强的太傻逼,直接换其他书上了。搞得我们全班比其他平行班C语言牛逼好多。只能说别学太死了。。。。能编程,这项目,就好了,不要去纠结没意义的题目啊。
    loveuqian
        37
    loveuqian  
       2015-02-10 09:36:29 +08:00
    <script type="text/javascript">
    var a = 0;
    a = (++a) + (++a) + (++a) + (++a);
    document.write(a)
    </script>

    答案是10喔
    jasonding
        38
    jasonding  
       2015-02-10 09:53:51 +08:00
    研究了下,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  
       2015-02-10 09:56:15 +08:00
    打印结果为10那一行写错了,cao
    a=(++a)+(++a) +(++a)+(++a) : a=1 + (++1) +(++(1 + (++1)))+(++(++(1 + (++1)))
    这样才是对的
    robertlyc
        40
    robertlyc  
       2015-02-10 10:20:04 +08:00
    没啥 为什么
    编译器就是这么做的 而且各家编译器还不同

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

    so,出现什么结果都有可能,就不要深究啦
    itsasony
        43
    itsasony  
       2015-02-10 10:46:38 +08:00
    @jasonding
    1+2+3+4
    Dongdong36
        44
    Dongdong36  
       2015-02-10 11:30:41 +08:00
    不需要知道为什么,因为没人会写这种代码,如果想知道原理,就拆分开,一点点试验,分析编译器的处理顺序,不同的编译器对于未定义的操作处理方法是不同的,曾经就遇到过gcc和VS的编译结果不同。
    BGLL
        45
    BGLL  
       2015-02-10 11:39:08 +08:00
    @frankzeng 有公司敢考这玩意(认真的考),当场走,这公司没救了
    BGLL
        46
    BGLL  
       2015-02-10 11:43:12 +08:00
    @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  
       2015-02-10 11:46:02 +08:00
    这是谭浩强书上的作业吧?
    clino
        48
    clino  
       2015-02-10 11:55:58 +08:00
    为什么我用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  
       2015-02-10 11:56:28 +08:00
    表示Golang直接syntax error: unexpected ++
    xuyuanp
        50
    xuyuanp  
       2015-02-10 12:04:14 +08:00
    谭浩强教的
    rushcheyo
        51
    rushcheyo  
       2015-02-10 12:10:55 +08:00
    @vzch 伪 vczh 是不是很好玩?
    frankzeng
        52
    frankzeng  
       2015-02-10 12:34:56 +08:00
    @BGLL 虽然不是这题,但也差不多啊

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

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

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

    facat
        64
    facat  
       2015-02-10 14:55:23 +08:00
    标准里面没有规定++运算符的优先级,是编译器自己实现的。
    lalalanet
        65
    lalalanet  
       2015-02-10 14:59:22 +08:00
    @facat 是这样的,这是分标准表达式,每个编译器怎么处理都是随意的。这种代码写出来就是找死。
    BGLL
        66
    BGLL  
       2015-02-10 15:05:31 +08:00
    @b821025551b
    难怪,那么多人喷谭浩强....
    onlyice
        67
    onlyice  
       2015-02-10 15:27:15 +08:00
    求不问这种问题。。
    自己搜一下就知道了。。
    vwok
        68
    vwok  
       2015-02-10 20:02:20 +08:00 via Android
    对于扯这种问题的,可以把四个括号去掉让他在算算等于多少
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3294 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:54 · PVG 20:54 · LAX 05:54 · JFK 08:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.