What actually happens when you replace comparison with assignment

So it seems like a lot of beginners tend to replace the comparison operator with the assignment operator. I understand the confusion, but what actually happens when you do this?

1
2
3
4
5
6
int c = 12;
int b = 7;

if(c == b)
   //Do something....

//Ok now let's just replace the comparison with assignment

if(c = b)
   //Do something...


The first part is obvious, we don't need to talk about that. But the second part:

First off, it assigns the value stored at b, into c. And then it performs the condition. So, this can boil down to if(12). A true is equal to one, and false is equal to zero (I believe, at least from C I think that's how it was). So unless you happen to assign a variable the value of 1, this type of situation will always be false? I seem to remember testing this before as I was helping a friend through a c++ class and he made this mistake, and the behavior was not as I expected. It actually went ahead and performed whatever it was, even though the value was not a 1. So what's the deal here? What exactly happens behind the scenes in these situations?

EDIT:

I guess I just found out that if you put a line of ----- in a code block here, it separates it all weird like. Interesting.
Last edited on
To my understanding, a = operator returns a reference to the variable on the left side after the assignment is preformed.

Now to be on topic, I believe its , false is 0 and anything else is true.
xD
Last edited on
Hmm, think you go in any more detail in that? Returning a reference? How does that do anything, when a reference is just an alias?
The definition of operator= is as follows(if I remember right...):

1
2
3
4
5
6
class object{
     object & operator=(const object & b){
      //do what you need to do
      return *this;
     }
};


this allows you to do things like

obj1=obj2=obj3=obj4;
blueberry is correct.

 
if(a = b)

is the same as:
1
2
a = b;
if(a)

is the same as:
1
2
a = b;
if(a != 0)

> think you go in any more detail in that?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

int main()
{
    struct A
    {
        A& operator= ( const A& that )
        { std::cout << "assign one object of type A to another\n" ; return *this ; }

        bool operator== ( const A& that ) const
        { std::cout << "compare equivalence of two object of type A\n" ; return true ; }

        operator bool () const
        { std::cout << "convert an object of type A to bool\n" ; return true ; }
    };

    A x, y ;
    
    if( x == y ) ;
    // prints: compare equivalence of two object of type A

    if( x = y ) ;
    // prints: assign one object of type A to another
    // prints: convert an object of type A to bool
}
Sure, a reference is just an alias, but it's an alias that always 'refers' to the object it is representing. Saying this:
1
2
3
int z = 9;
int &a = z;
int b = a;

is correct, because using 'a' anywhere will always refer directly to the value it references (here z). References aren't like pointers, which are an actual objects themselves.
In the case of your assignment:
1
2
3
4
int a = 9, b = 0;
if(b = a){ DoStuff; }
//This will return a reference (the actual value of) b back, which in this case will have
//been changed to 9, which being !=0 is true. 
Last edited on
Aah I get it. So, whenever this happens, as long as the right side operand is a non zero, the condition will result in a true?
Yep, and that's why we get all the confused first posts xD
Ah ok cool :) I always see these posts, and I know why they have issues with it, but I was wanting a more deep understanding of what exactly was going on when that mistake is made.
Aah I get it. So, whenever this happens, as long as the right side operand is a non zero, the condition will result in a true?


Not quite. In an attempt to oversimplify, you're making it more complicated.

The right side isn't a clear-cut indicator because there are truncation issues.

Example:

1
2
3
4
5
6
uint8_t a = 5;
int b = 0x100;  // too large for uint8_t
if( a = b )
{
  // not executed, because a == 0
}


If you want "rules", they would be this:

- Assuming the left side is a basic type: As long as it's nonzero after assignment.
- For complex types that can be implicitly cast to a bool: As long as cast to bool returns true after assignment.
- For complex types that can't be implicitly cast to a bool: compiler error.


But that's overly complicated.

Really, it's as simple as this:

1
2
3
4
5
6
//this:
if(a = b)

// is the same as this:
a = b;
if(a)


If you think of it that way, you'll never go wrong.
@Disch,

That is brilliantly simple!
@ResidentBiscuit

What actually happens when you replace comparison with assignment


The assignment will replace the comparision.:)

Assignment is an expression. As any expression it has a result. So the result of the assignment expression will be used in if statement if it can be converted to
bool. For example scalar types can be converted to bool. So an expression of a scalar type can be used in if statemennt.


Topic archived. No new replies allowed.