search

Home  >  Q&A  >  body text

C++条件运算符的运算问题,求指教

  1. 问题:为什么输出的y是5,而不是6?

  2. 相关代码

    #include <iostream>
    
    int main() {
        int someValue = 1, x = 1, y = 5;
        std::cout << (someValue ? ++x, ++y : --x, --y) << std::endl;
        
        return 0;
    }
  3. 相关贴图(测试环境:Xcode 7.3.1 OSX EI Capitan)

  4. 个人思考

    • 思考1:因为条件运算符?:是右结合,所以先执行--y,y变成4,再执行++y,y变成5。疑问:条件运算符的执行顺序是:先求解表达式1,若为非0(真)则求解表达式2,此时表达式2的值就作为整个条件表达式的值。那为什么还会出现这样的问题

    • 思考2:这句语句中的第二第三个运算对象指向同一个对象x,y;而且两个都修改了对象的值,这种行为是未定义的。疑问:但是?:运算符不是已经确定了运算顺序码?为什么还会出现这样的问题?

PHPzPHPz2773 days ago503

reply all(3)I'll reply

  • 天蓬老师

    天蓬老师2017-04-17 14:21:05

    Foreword

    Every time I meet people who ask questions about C++, they are all relatively basic questions like this. I always say this:
    Disassembly is a skill that C++ programmers must master! ! !
    Disassembly is a skill that C++ programmers must master! ! !
    Disassembly is a skill that C++ programmers must master! ! !
    Otherwise, you will be like a blind man when debugging a program, you can only rely on guessing.

    Analysis

    In fact, based on experience, I think it is far less complicated, and it is not an undefined behavior, but a problem of operator scope.
    The correct execution order of this expression is as follows:

    if(1){
        ++x;//这句没有用,在release模式下会被编译器优化掉
        ++y;//y+1
    }else{
        --x;
    }
    --y;//y-1
    cout<<y<<endl;

    is obvious at a glance because the : operator has higher precedence than ,. The conditions before : are true and can only be executed sequentially, while the subsequent , exceeds the scope of the : operator. Therefore, whether the condition is true or not, --y will definitely be executed.
    So the correct way to write it is to add 括号.

    auto y=someValue ? (++x, ++y) : (--x, --y);
    //y=6

    Disassembly

    00F0625E  mov         dword ptr [someValue],1  
    00F06265  mov         dword ptr [x],1  
    00F0626C  mov         dword ptr [y],5  
    00F06273  cmp         dword ptr [someValue],0  
    00F06277  je          main+56h (0F06296h)  ;判断条件是否成立
    00F06279  mov         eax,dword ptr [x]  
    00F0627C  add         eax,1  
    00F0627F  mov         dword ptr [x],eax  
    00F06282  mov         ecx,dword ptr [y]  
    00F06285  add         ecx,1  ;y的值+1变成了6
    00F06288  mov         dword ptr [y],ecx  
    00F0628B  mov         edx,dword ptr [y]  
    00F0628E  mov         dword ptr [ebp-0E8h],edx
    00F062A8  mov         edx,dword ptr [y]  
    00F062AB  sub         edx,1  ;再减一变成5
    00F062AE  mov         dword ptr [y],edx ;传值返回   

    reply
    0
  • 迷茫

    迷茫2017-04-17 14:21:05

    Because the ?: operator has a higher priority than the , operator, the expression (someValue ? ++x, ++y : --x, --y) is equivalent to ((someValue ? (++x, ++y) : --x), --y) so the conditional operation ++y will be followed by --y, so y outputs 5

    reply
    0
  • PHPz

    PHPz2017-04-17 14:21:05

    First of all, a correction, any order of operations is defined. Most of the undefined behavior is for the evaluation order rather than the operation order.

    There are three evaluation orders defined in

    c: A ? B : C, A, B, A && B (of course there is also ||). Your code above can be accused of being unreadable, but it cannot be said to be undefined.

    The result is pretty clear, it’s 5.

    reply
    0
  • Cancelreply