So can someone help me grasp all the (or most of the relevant) situations of an assignment inside something like an if(...) or while(...), etc?
What I mean is like:<
if (a = b)
...
is the shorthand for:
a = b;
if (a != 0)
...
In a while statement, assignment within the condition enables the DRY principle:
while (a = b)
{
...
}
is shorthand for (notice how I had to replicate the assignment so that it is done right before the condition check):
a = b;
while (a != 0)
{
...
a = b;
}
That said, one classic issue with code like this is knowing whether the code intended to do an assignment or if the code forget an '=' when the intent was to write '==' (i.e. should that have been while (a == b)
.
Because of this, you should never write just a plain assignment (gcc will issue a warning such as "suggest parentheses around assignment used as truth value"). If you want to use assignment in a control structure, you should always surround it with extra parentheses and explicitly add the not-equal:
if ((a = b) != 0)
...
while ((a = b) != 0)
...
An assignment "operation" also returns a value. It is the type and value of the expression. If handled by an if
type statement:
while (expr)
do
... until (expr)
if (expr)
?
(true value) : false valueexpr is evaluated. If it is nonzero, it is true. If zero, it is false.
In both examples you listed, inside the parentheses is evaluated to true if a is non-zero after the assignment.
In a more common case, you compare a variable with a constant, to avoid this problem, some coding standards require that you write the constant first.
if (A_CONSTANT = var_a)
this would be caught by the compiler, whereas,
if (var_a = A_CONSTANT)
won't.
The return type of the assignment is the left hand value, it's what allows statements like a = b = c
to compile. In your example:
while(a = &c)
{
}
Returns true when "a" is true, after it has been assigned the value of &c.
In C++ an attribution evaluates to the value being attributed:
int c = 5; // evaluates to 5, as you can see if you print it out
float pi = CalculatePi(); // evaluates to the result
// of the call to the CalculatePi function
So, you statements:
if (a = b) { }
while (a = &c) { }
are roughly equivalent to:
a = b
if (b) { }
a = &c
while (&c) { }
which are the same as
a = b
if (a) { }
a = &c
while (a) { }
And what about those if (a)
etc when they are not booleans? Well, if they are integers, 0 is false, the rest is true. This (one "zero" value -> false, the rest -> true) usually holds, but you should really refer to a C++ reference to be sure (however note that writting if (a == 0)
is not much more difficult than if (!a)
, being much simpler to the reader).
Anyways, you should always avoid side-effects that obscure your code.
You should never need to do if (a = b)
: you can achieve exactly the same thing in other ways that are more clear and that won't look like a mistake (if I read a code like if (a = b)
the first thing that comes to my mind is that the developper who wrote that made a mistake; the second, if I triple-check that it is correct, is that I hate him! :-)
Good luck
An assignment statement evaluates to the new value of the variable assigned to (barring bizarre overloads of operator=). If the assignment happens in a boolean context it will then depend on the type of that value how it is treated. If the value is a bool, it is of course treated as a bool. If the value is a numeric value, a non-zero value is treated as true. If the value is a pointer, a non-NULL value is treated as true. If it is a object, the compiler will attempt to convert it to a boolean value (e.g. operator bool). If that is not possible, the compiler will attempt to convert the object to a value that is convertible to bool (e.g. a pointer type, or a numeric type such as int). Finally, if there is no conversion to be performed, or there are multiple possible conversions (e.g. the object defines operator int and operator foo*), the code will fail to compile.