简体   繁体   中英

C++ comparison with an assignment expression be the right hand side expression

I am currently working with a problem about data structure using C++. I am going to check whether the nodes in a singly linked list are sorted in ascending order or not. Here comes some details of my code

Node.cpp

class Node
{
   public:
     double data;       
     Node* next;    
};

For the part that problem occurs,

double preValue = sLL.head->data;       
Node *curNode = sLL.head->next;     

    do
    {
        if (preValue > (preValue = curNode->data))  // Problem occur in this line   
            return false;
    }while (curNode = curNode->next);

As the order of evaluation of '>' operator is evaluating the left hand side expression and then the right hand side expression

AND

the assignment operator would return a reference of the lvalue.

Therefore, preValue > (preValue = curNode->data) should compares the last node and the current node and assign the data of the next node after the comparison is done. Therefore, I think my implementation should be valid.

However, the result of if(preValue > (preValue = curNode->data)) is out of my expected, when comparing a preValue which is bigger than the new preValue , it keeps returning false.

I have tried to print out the return value of the if statement, it always return 0 whenever the left expression if greater or smaller than the right expression. I cannot understand why this happen. Could anyone tell me what mistake did I made?

ps the program work fine with the following implementation

double preValue = list.head->data;      
Node *curNode = list.head->next;            

do
{
    if (preValue > curNode->data)       // Check ascending order
        return false;

    preValue = curNode->data;

}while (curNode = curNode->next);       

This line is Undefined Behavior:

if (preValue > (preValue = curNode->data))  // Problem occur in this line

because you're assigning to a variable ( preValue ) and reading from that same variable, and the read is not used to determine the value written .

From C++03 §5/4 [expr] :

[...] Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

A sequence point occurs after full expressions (ie semicolon-terminated expressions or statements), as well as after the first operands of the && , || , ?: , and , operators. All other operators (including the > operator) do not have sequence points between the evaluations of their arguments. Sequence points also occur in a few other places not relevant to this question.

The fix, as you said, is to just break it apart so that the assignment happens in a separate statement from the comparison.

When I compile this code with GCC with the -Wall compiler flag, I get this warning:

warning: operation on ‘preValue’ may be undefined [-Wsequence-point]

I highly recommend you always compile with -Wall and -Werror so that these errors get flagged immediately by the compiler and you can correct them.

This line

if (preValue > (preValue = curNode->data)) 

is an undefined behaviour. See the concepts of sequence points . An expression can modify its objects only once between two sequence points and '>' is not a sequence point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM