Are logical OR and comma operators equivalent? - c++

Today I found a syntax thing I had never seen before. Are || and , the same?
bool f() {
cout << "f";
return true;
}
bool g() {
cout << "g";
return true;
}
int main() {
if(f(),g())
{
cout<<"OK with ,";
}
cout<<endl;
if(f()||g())
{
cout<<"OK with ||";
}
return 0;
}
From the output of this program, it seems so:
fgOK with ,
fOK with ||
Are they the same exact thing or are there any little differences?

f(),g() means evaluate f() then evaluate g() and return g() since your g() returns true it is that what is returned to if
So, no, the operators are totally different.
You can see the difference if you modify your function to return false from g(). The condition f()||g() will still evaluate to true while f(),g() will return false.

This (comma operator)
if(f(),g())
will evaluate both f() and g() and return the value of the second operand g()
The logical OR operator
if(f()||g())
will not evaluate g() if f() evaluates to true. This is known as short-circuit evaluation - if f() returns true, then the logical OR condition is already satisfied - hence there is no point evaluating g().
So they are NOT the same at all even though under certain conditions you may see the same overall behaviour.

|| is the logical OR operator and by standard it follows short-circuit evaluation (i.e. it won't evaluate the second operand if the first already suffices to determine the entire logical expression)
, is the comma operator that evaluates both but just return the value of the second operand.
By the way you should be seeing something like:
fgOK with ,
fOK with ||
the reason why you're not seeing it might be because you're using a compiler that doesn't strictly follow the standards (I suspect MSVC..)
http://ideone.com/8dSFiY

They are completely different operators that serve completely different purposes.
The main difference is that:
The , operator (unless overloaded) will evaluate all of its arguments and return the last one, no matter what.
The || operator will evaluate all the arguments until it reaches the first trueish value and will not evaluate the rest.
This is also the reason why the output, you are claiming to receive, is wrong.

Related

Logical operator execution order

I have though about operator overloading and come with an interesting code:
#include <iostream>
class A {
public:
operator bool() {
return true;
}
bool operator!() {
return false;
}
};
int main() {
A a;
if (!a) {
std::cout << "HELLO";
} else {
std::cout << "WORLD";
}
std::cout << std::endl;
return 0;
}
What will be called first and what after? And why? Is this described anywhere in the cppreference?
P.S. For downvoters and others who think I could not execute this code by myself. I could. I did. I have changed it many times to see it's behavior. So what? This is not an explanation. I have asked for a reference which clearly states what rule this code obeys. The information how it works on my machine does not answer the question - what if this is not even portable across different environments (OSes, maybe processors, and so on)?
How it works is simple. The compiler parses the source and sees if(!a). It then checks if A defines an operator!. Just so happens that it does. So that gets called.
If it had seen if(a) it would have checked that an A is convertible to something which can be used in the condition of an if. Just so happens that it is indeed convertible.
If there had been no operator!, the compiler would have instead checked that an A can be converted to something which may be logically negated. Then the conversion to bool would have been performed.
BTW, the conversion will happen even in surprising places. For instance a + 1 will compile. Not what we want, I think. It's best to allow it only where a bool is contextually expected. You do that by marking the conversion operator explicit:
explicit operator bool() {
return true;
}
!a is no more than syntactic sugar for a.operator!(), which you have defined: that's the compiler's preferred choice.
So the conversion to bool operator is never a candidate.
You could contrive the latter by writing
if (!(bool)a) {

Evaluation order of Operator *

I have the following piece of code :
int f(int &x, int c){
c = c - 1;
if (c == 0) return 1;
x = x + 1;
return f(x, c)*x;
}
Now, suppose I call the above function like this :
int p = 5;
std::cout << f(p, p) << std::endl;
The output is 9^4, since x is passed by reference, hence the final value of x should be 9, but when the return statement of the above function is changed to :
return x*f(x, c);
the output is 3024 (6*7*8*9). Why is there a difference in output ? Has it anything to do with the order of evaluation of Operator* ? If we are asked to predict the output of the above piece of code, is it fixed, compiler-dependent or unspecified ?
When you write:
f(x,c)*x
the compiler may choose to retrieve the stored value in x (for the second operand) either before or after calling f. So there are many possible ways that execution could proceed. The compiler does not have to use any consistency in this choice.
To avoid the problem you could write:
auto x_temp = x;
return f(x, c) * x_temp;
Note: It is unspecified behaviour; not undefined behaviour because there is a sequence point before and after any function call (or in C++11 terminology, statements within a function are indeterminately-sequenced with respect to the calling code, not unsequenced).
The cause is that f() function has side effect on its x parameter. The variable passed to this parameter is incremented by the value of the second parameter c when the function returns.
Therefore when you swap the order of the operand, you get different results as x contains different values before and after the function is called.
However, note that behaviour of the code written in such way is undefined as compiler is free to swap evaluation of operand in any order. So it can behave differently on different platforms, compilers or even with different optimization settings. Because of that it's generally necessary to avoid such side effects. For details see http://en.cppreference.com/w/c/language/eval_order

How works if() statement

I have a simple question for optimizing my code.
bool myfunc();
if (false && true && myfunc())
{
}
Will the function myfunc() be called ??
Because C++ have short-circuit evaluation of conditions, no the function will not be called since the firstfalse makes the whole expression false anyway.
If you change the order, so you put the function call first (i.e. myfunc() && false && true) then the function will be called. The result of the expression will still be false though, no matter what myfunc returns.
No.
&& and || have short-circuit evaluation, that is, once the result is definitely known (false for && and true for ||) evaluation stops. And it's always strictly left-to-right.
In this case the compiler might even choose to elide the if statement completely, since the condition at compile-time is known to be false and thus the code afterwards is unreachable.
No, myfunc() will not be called, because of the first false, compiler will stop there. It's called short circuit evaluation.

Operator commutativity for inequality != in C++

I have a quick question about the following expression:
int a_variable = 0;
if(0!=a_variable)
a_variable=1;
what is the difference between "(0 != a_variable)" and "(a_variable != 0)" ?
I dont have any errors for now but is this a wrong way to use it??
if you forget the !, the first will give an error (0 = a_variable) and the second will wreak havoc (a_variable = 0).
Also, with user-defined operators the second form can be implemented with a member function while the first can only be a non-member (possibly friend) function. And it's possible, although a REALLY bad idea, to define the two forms in different ways. Of course since a_variable is an int then there are no user-defined operators in effect in this example.
There is no difference between 0 != x and x != 0.
Any difference it may make is the order in which the arguments will be evaluated. a != b would conventionally evaluate a, then evaluate b and compare them, while b != a would do it the other way round. However, I heard somewhere that the order of evaluation is undefined in some cases.
It doesn't make a big difference with variables or numbers (unless the variable is a class with overloaded != operator), but it may make a difference when you're comparing results of some function calls.
Consider
int x = 1;
int f() {
x = -1;
return x;
}
int g() {
return x;
}
Assuming the operands are evaluated from left to right, then calling (f() != g()) would yield false, because f() will evalute to -1 and g() to -1 - while (g() != f()) would yield true, because g() will evaluate to 1 and f() - to -1.
This is just an example - better avoid writing such code in real life!

In C++ what causes an assignment to evaluate as true or false when used in a control structure?

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)
or
while(a = &c)
{
}
etc...
When will it evaluate as true, and when will it evaluate as false? Does this change at all depending on the types used in the assignment? What about when there are pointers involved?
Thanks.
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 "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)
or the ternary operator (expr) ? (true value) : false value
expr is evaluated. If it is nonzero, it is true. If zero, it is false.
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 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.
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.
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)
...