igboy
V2EX  ›  C

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

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

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

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

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

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

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

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

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

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