Skip to main content
GameDev.net gamedev.net
🔒 Locked

The difference between = and ==

Started by totaljj May 25, 2006 at 11:45 AM 18 replies 2.6k views
Original Post
totaljj
totaljj
if (time_step=intercept_time) if (time_step==intercept_time) both compiled. But the one above have right effect for my game. What is the differnece?
Smit
Smit
The top one is assigning "intercept_time" to "time_step" whereas the bottom one is comparing "intercept_time" to "time_step".
mumpo
mumpo
= is the assignment operator. == is the equality operator. (A = B) changes A's value to that of B and returns/evaluates to a reference to B. (A == B) doesn't change A or B, but returns/evaluates to true if A's value is the same as B's, or false if it isn't. If statements should almost always be using ==, not =; using == with an if statment tests for equality, while using = change's the left operand's value and then tests if that value is nonzero. For clarity and to make tracking down bugs easier, if you find yourself in a situation where if(A = B) actually does what you want, you should probably move the assignment to it's own line above the if statment and then stick an explicit test of A's value in the it statement, such as (0 != A).
janta
janta
Quote:
Original post by Anonymous Poster
I'm assuming you're using C, C++, Java, or a syntaxic similar language. Then the = is for assignations, and the == tests for equality. The = always evaluates to TRUE, whereas == evaluates to TRUE if and only if the left and right parts of the expression are equal.


You sure of that ?
I think that

if( x = expr() )


evaluates the same as

if( expr() )


and

x = expr();if( x )


Am I wrong ? At least do I think it's like that in C++ (and probably C) I don't remember well about Java, It might always evaluate to true.
janta
janta
In addition to what peple said, many FAQs advise you that in case of comparing a variable to another value, you do

if( func() == var )if( 10 == var )

rather than
if( var == func() )if( var == 10 )


so as in case you just miss an equal sign, the compiler notice there is something very wrong.

if( 10 = var ) // Compiler will go on strike

if( var = 10 ) // you will have a hard time finding such a bug
Palidine
Palidine
Quote:
Original post by janta
Quote:
Original post by Anonymous Poster
I'm assuming you're using C, C++, Java, or a syntaxic similar language. Then the = is for assignations, and the == tests for equality. The = always evaluates to TRUE, whereas == evaluates to TRUE if and only if the left and right parts of the expression are equal.


You sure of that ?


Janta is correct, the = operator does NOT always evaluate to TRUE. It evaluates to TRUE iff the value that's being assigned is non-zero. so...

(x = 100) -> TRUE
(x = 0) -> FALSE

That's how you can do statements like:

if ( MyObject *foo = findObjectInDatabase() ){    //this will execute iff findObjectInDatabase returns a non-NULL value}else{    //this will execute if findObjectInDatabase returns NULL}


-me

CTar
CTar
Quote:
Original post by janta
Quote:
Original post by Anonymous Poster
I'm assuming you're using C, C++, Java, or a syntaxic similar language. Then the = is for assignations, and the == tests for equality. The = always evaluates to TRUE, whereas == evaluates to TRUE if and only if the left and right parts of the expression are equal.


You sure of that ?
I think that

if( x = expr() )


evaluates the same as

if( expr() )


and

x = expr();if( x )


Am I wrong ? At least do I think it's like that in C++ (and probably C) I don't remember well about Java, It might always evaluate to true.


You're both wrong, but the AP is totally wrong.
a=b evaluates to a after the assignment
a==b evaluates to the result of the operator== with a and b as the arguments.

Also
T a = b;if( b ){}

Is not necessarily the same as
if(a = b){}

Consider the following:
#include <iostream>// _index of -1 means uninitialized// when converted to bool the object will evaluate to true// if the index is initialized and false if it isn't.class array_index{    int _index;public:    array_index() : _index(-1) {}    array_index( int raw_index ) : _index(raw_index){}    array_index& operator=(int rhs)    {        _index = rhs;        return (*this);    }    operator bool()const    {        return (_index != -1);    }};int main(){    array_index x;    if( x = 0 )    {        std::cout << "x = 0 is true" << std::endl;    }    else    {        std::cout << "x = 0 is not true" << std::endl;    }    if( 0 )    {        std::cout << "0 is true" << std::endl;    }    else    {        std::cout << "0 is not true" << std::endl;    }    return 0;}


Janta: What if MyObject isn't an integer type? "if ( obj )" tries to implicitly convert obj to a boolean.

[integer = signed char, char, unsigned char, signed short int, unsigned short int, signed int, unsigned int, unsigned long int or signed long int]
If an obj is of type bool no conversion will go on.
If obj is of type integer, then obj will be converted to false iff obj is zero, else it will be converted to true.
If obj is of type float or double a compile time error will occur.
If obj is a non-primitive type it will try to make the shortest implcit conversion from the type to bool, which could be T -> bool if an operator bool is present, T -> integer -> bool if an operator int is present and an operator bool isn't, etc.
Luctus
Luctus
Quote:
Original post by Anonymous Poster
Also, in Java, = does not evaluate to anything, and so trying if( foo = bar ) will get you a nice compiler error.


Wrong. Java handles = and == the same way as C and C++ which CTar described above. The differance is that java only allow boolean types in if statements, whereas C and C++ will accept anything that can be interpreted as boolean or integer.
-LuctusIn the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move - Douglas Adams
janta
janta
Quote:
Original post by CTar
Janta: What if MyObject isn't an integer type? "if ( obj )" tries to implicitly convert obj to a boolean.

[integer = signed char, char, unsigned char, signed short int, unsigned short int, signed int, unsigned int, unsigned long int or signed long int]


OMG you trapped me. Ok, so you've proved that I could be wrong in some unusual situation.

What I call a usual situation is when someone is not using some obscure operator overloading ;) And in my opinion, for a class C to have an overloaded '=' operator which does not take a C& argument is indeed obfuscated. The same remark goes for you bool cast operator IMHO...

When some conversion or any non-obvious operation is occurring, then it should be stated loud and clear like a ::SetIndex(0) and a IsInitialized()
Then there would be no way to combine those both operation in a if statement, and you would have to do sth like:

array_index x;x.SetIndex(0); // or if( x.IsInitialized() ){ ... }


But ok, you trapped me :) I just meant "when '=' is the gool old real '=' operator and using good old integral types" :p

What you've just done is a tricky class wich allowed you to "trickytransparently" convert '0' into 'true'.

I think we both know what each other mean, so let's not confuse anybody hehe...

Cheers.
Janta
CTar
CTar
Quote:
Original post by janta
What you've just done is a tricky class wich allowed you to "trickytransparently" convert '0' into 'true'.


The problem is that in a real project, with bigger, more complicated classes a similar logic "error" might be made. Actually I just went looking for a similar real-world example, I found something similar in OpenEye's OEChem library's class OEResidue. The description of operator bool is:
Quote:
Determine whether any field of an OEResidue has a non-default value.

Which is basically the same thing my array_index's operator bool did. Personally I don't think this is good design, but these kind of things happen in real software so one have to know the exact rules (which you do, you just only thought about integral types). Also a similar error is most likely to occur if a class have an operator T where T is an integral type, then the class will first be converted to T then to bool. A more realistic example might be an Angle class where the actual angle is stored as an integral type T, the Angle have an operator= taking a const reference of another Angle object and a constructor taking T. The constructor will wrap around so that the number stays in the range 0 to 360 (we measure in degrees). The class also have an implicit conversion to T.
Angle::Angle( T in ) : actual_data( in % 360 ){}Angle::operator T(){return actual_data;}Angle& Angle::operator=( const Angle& rhs){  actual_data = rhs;  return (*this);}


Now consider:
Angle x;bool b = static_cast<bool>(x = 720);

Since x will store 720%360 = 0 b will be false. This is not that bad design, and I believe many people could do something like this.
janta
janta
Yes, and that would be a good thing don't you think ?
I mean, something like

if( angle == 0 )

is probably meant to do something every time the angle is 0, and 720 *is* 0 in term of an angle, so it's just better that the conditin is triggered too for every multiple of 360.

Oh wait, is this a neverending conversation ? :)

Anyway, I think you are since using if( x = expr() ) gains you nothing more than x = expr(); if(x) and the latter is just less likely to cause error.

So you get this one hehe...

See ya.
Janta
taby
taby
Quote:
Original post by Verg
Another aside:

If you DO decide to use an assignment as a test, make sure and comment it so that future coders knew you did it on purpose.

EG:

if (foo = bar())     // ASSIGNMENT...


"foo = bar()" might look like a bug to someone else.



Chad



Or even specify completely...

if(0 != (foo = bar()))
{
...
}
ChaosEngine
ChaosEngine
Quote:
Original post by taby
Quote:
Original post by Verg
Another aside:

If you DO decide to use an assignment as a test, make sure and comment it so that future coders knew you did it on purpose.

EG:

if (foo = bar())     // ASSIGNMENT...


"foo = bar()" might look like a bug to someone else.



Chad



Or even specify completely...

if(0 != (foo = bar()))
{
...
}


good god, that's ugly. Please don't do that.

there's nothing wrong with
if (SomeObject *pObj = FuncReturningObjPointer()){   // do stuff with pObj   }

it's clean, it limits the scope of pObj, and it's obvious it's not meant to be an equality test

the same cannot be said for
SomeObject *pObj = NULL;if (pObj = FuncReturningObjPointer()){   // do stuff with pObj   }

there's really no need for this. If pObj is null, what use is it?

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Verg
Verg
Quote:
Original post by ChaosEngine
Quote:
Original post by taby
Quote:
Original post by Verg
Another aside:

If you DO decide to use an assignment as a test, make sure and comment it so that future coders knew you did it on purpose.

EG:

if (foo = bar())     // ASSIGNMENT...


"foo = bar()" might look like a bug to someone else.



Chad



Or even specify completely...

if(0 != (foo = bar()))
{
...
}


good god, that's ugly. Please don't do that.

there's nothing wrong with
if (SomeObject *pObj = FuncReturningObjPointer()){   // do stuff with pObj   }

it's clean, it limits the scope of pObj, and it's obvious it's not meant to be an equality test

the same cannot be said for
SomeObject *pObj = NULL;if (pObj = FuncReturningObjPointer()){   // do stuff with pObj   }

there's really no need for this. If pObj is null, what use is it?


If it's an obvious assignment, like the one you show, there's no need for a comment.

But it doesn't hurt to comment.

Aprosenf
Aprosenf
It's not uncommon to see statements such as:

if((result = someOperation()) != GOOD)  // handle error


Also, WRT Java: since Java specifically only permits booleans as the condition of an if or white statement, the only time confusing = with == would result in compilation without an error is if both objects were of type boolean, e.g.:

boolean a, b;...if(a = b) // Sets a to b and returns the result as the condition of the if statement


Eclipse has a setting which will give you a warning if you have the above construct.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.