Ran across some code that used this, which led me to wonder.
if(condition) foo = bar();
condition && (foo = bar());
Are these two segments of code equal to a compiler? If not, in what ways would they differ?
Due to operator precendence, the latter is interpreted as:
(condition && foo) = bar();
Additionally, there is a possibility of && being overloaded, which may result in pretty much anything.
So in short: they are not equal at all - at least in general case.
The first version is just a plain old statement.
The second version is an expression that will return the result of the entire expression. That probably allows some tricky one-line syntax that, as per usual, could potentially make code more readable but will more likely make it more complex and harder to parse quickly due to unfamiliarity.
IMO either use it everywhere consistently so that readers of your code get used to it, or don't use it at all.
Unless && is overloaded for the combination of types of condition and foo they will have identical behavior - the latter will work this way:
bool result;
if( !condition ) {
result = false;
} else {
foo = bar();
result = foo != 0;
}
and result gets ignored
that's usual short-circuiting - if the first component of && is false the second is not evaluated.
IMO the second variant is much less readable.
Unless condition && foo evaluates to an lvalue , condition && foo = bar(); is meaningless.
There is a compiler error: invalid l-value. To have same functionality you must use
conticion ? foo = bar( ) : <other accion>;
If && is not overloaded for neither condition nor foo:
condition && (foo = bar());
will be treated as
(condition.operator bool()) && (foo = bar());
if (condition.operator bool()) isn't true, (foo = bar()) won't be executed and vice versa.
Related
This question already has answers here:
Declaring and initializing a variable in a Conditional or Control statement in C++
(9 answers)
Closed 7 years ago.
I want to create an if where a variable is declared, assigned and checked. If the variable's value is acceptable, I want to use it inside if body. Here's an example of how I thought I could do that:
if ((int result = Foo()) != 0) {
// use result
}
I assumed that Foo() returns some value, which is assigned to result, and returned by assignment operator =, and finally checked against 0 in != 0. Unfortunately, it results in a compilation error:
main.cpp:31:10: error: expected primary-expression before ‘int’
if ((int i = Foo()) != 0)
^
main.cpp:31:10: error: expected ‘)’ before ‘int’
Why is this error happening? And what ways could there be to fix it?
The logic is supported, but declaring a variable within an if statement and using it this way is not. The reason is related to the fact that an initializer works differently than a regular assignment, but working around this is easy and trivial.
Just do something like this instead.
int result;
if ((result = Foo()) != 0) {
// use result
}
Your reasoning seems to be based on the assumption that = in
if ((int result = Foo()) != 0)
is an assignment operator and that int result = Foo() is "just an expression" that evaluates to something.
This is not true.
The int result = Foo() part is not an expression in C++. It is a declaration with an initializer. The = in initializer syntax is not an assignment operator at all. It is just a syntactic element that coincidentally uses the same character as assignment operator. The int result = Foo() is not an expression and it does not "evaluate" to any result.
Because if the above, support for something like
if (int result = Foo())
requires special treatment, which severely limits the flexibility of this syntax. What you tried in your code goes outside the bounds of what's allowed by that special treatment.
Bjarne uses this construct as a scope restrictor in 6.3.2.1 The C++ programming language as a recommendation.
Use:
if (int result = Foo()) {
// use non-zero result
}
It is particularly useful with pointers
if (Foo* result = GetFoo()) {
// use valid Foo
}
The !=0 part is redundant as truthiness is !=0.
The extended construct with the comparison is not allowed.
Further discussion of this construct from here
It fails because it's illegal. It's also ugly. #Jonathan Wood suggested declaring the variable outside the if. I suggest calling Foo outside, too:
int result = Foo();
if(result!=0) ...
The (x=f())!=y construct, while legal as an if condition, only makes sense in a loop, where
`while((c=getchar())!='\n)
... do something with c ...
Is the shorter and nicer equivalent of
c = getchar();
while(c!='\n')
{
...
c = getchar(c);
}
It saves writing the call to getchar() twice. It saves nothing when used in an if, so there's no point in using it.
Try this:
if ( int i = (Foo() != 0) ? Foo() : 0 ){
cout << "Hello. Number i = " << i;
}
I was wondering if one is inefficient over the other (two codes below)?
if ( abc & myType == myType )
{
if (myValue)
{
// do something
}
}
OR
if ( (abc & myType) && myValue )
{
// do something
}
They are not equivalent, a "corrected" second one would be
if ( (abc & myType == myType) && myValue )
{
// do something
}
In this case, any decent compiler will emit the same code for both.
Also, it's almost never sensible to do this kind of micro-optimization - you waste time around a difference that will be at most of one or two assembly instruction, maybe even in a code path that isn't critical. Here, where there's no real difference in performance, the real optimization to do is towards clarity of your code.
Real optimization is about not caring about these micro-differences (which are probably already taken of by the compiler), and instead profiling the code to find the real bottlenecks.
A few others have pointed out that the two are not equivalent for this reason:
if (abc & myType == myType )
{
if (myValue) {}
}
// OR
if ( (abc & myType) && myValue ) // missing myType == myType
{}
However there is a second reason the two are not equivalent: the == operator has higher precedence than the & operator (see this link). Your first expression therefore evaluates as follows:
if (abc & myType == myType) // Evaluates to (abc & true)
{
if (myValue) {}
}
You probably intended this:
if ((abc & myType) == myType) // Now the bitwise and happens before
// the comparison is made
{
if (myValue) {}
}
To avoid exactly this kind of bug, I always use parentheses to enforce precedence any time there is any possibility of ambiguity from a human's perspective (even though the compiler will never find it ambiguous), on the assumption that the reader has no clue what the actual precedences are. This has the added benefit of making the code easier to read.
In either C or C++, is there a conclusive difference between using !(variable) and (!variable) in an if-statement, such as:
if (!(variable)) { .. // do something }
or
if (!variable && !(variable2)) { .. // do something }
such that one version delivers a different result over the other?
Its all about order of operation. Using !(variable) will evaluation all conditions inside of the parenthesis then do the ! (or NOT) to determine whether to enter the if statement where-as (!variable will do the NOT specifically on the variable itself.
So in the situations:
!(true && false) = true
!(true && true) = false
(!true && !false) = false
(!true && true) = false
!(true && !false) = false
...and so on
Hope this helped.
The only way it would make a difference is if the variable is an expression, then its a matter of operator precedence. Otherwise && has lower precedence than !
There is no difference between
!(variable)
and
(!variable)
but if you are using operators that has different precedence you will have a difference. For example, if you write
!(varible1 && variable2)
is not the same as
!varible1 && variable2
because the NOT will be applid to the whole operation in the first case and only to varible1 in the second case.
May be you are getting a problem with the evaluation, C has lazy evaluation, so when the execution detects that boolean evaluation has a result, it doesn't try the other values. So, now consider instead of variables you have functions.
int foo() { printf("foo\n"); return 1; }
int bar() { printf("bar\n"); return 0; }
If you write
if (foo() && bar()) { ... }
you will get
foo
bar
but if you write
if (bar() && foo()) { ... }
you will only get
bar
because the evaluation will be false, doesn't matter the result of foo
No, in your example the first one (although the parens are unbalanced :)) behaves exactly like it would if there were no parentheses, and the second behaves the same way. You can even do this
if ((!((((variable)))))) { ... }
But don't :)
They should never evaluate to different things. Parentheses used this way are really for grouping operations, but in this case, you're not grouping any operations, just the expression itself.
So !(x) is just a pedantic way of writing !x
Now, if you had an operation inside the parentheses, that's where the differences start.
(I don't have a serious need for this answer, I am just inquisitive.)
Can every if-else construct be replaced by an equivalent conditional expression using the conditional operator ?:?
Does every if-else constructs can be replaced by an equivalent conditional expression using conditional operator?
No, you've asked this backwards. The "bodies" of if/else contain statements, and it is not possible to turn every statement into an expression, such as try, while, break statements, as well as declarations. Many "statements" are really expressions in disguise, however:
++i;
blah = 42;
some_method(a,b,c);
All of these are statements which consist of one expression (increment, assignment, function-call, respectively) and could be turned into expressions within a conditional.
So, let's reverse the question, since it sounds like you really want to know how equivalent if/else statements are to ternary conditional expressions: Can every conditional expression be replaced by equivalent if/else statements? Almost all, yes. A common example is return statements:
return cond ? t : f;
// becomes:
if (cond) return t;
else return f;
But also other expressions:
n = (cond ? t : f);
// becomes:
if (cond) n = t;
else n = f;
Which starts to point to where conditional expressions cannot be easily replaced: initializations. Since you can only initialize an object once, you must break up an initialization that uses a conditional into using an explicit temporary variable instead:
T obj (cond ? t : f);
// becomes:
SomeType temp;
if (cond) temp = t;
else temp = f;
T obj (temp);
Notice this is much more tedious/cumbersome, and requires something type-dependent if SomeType cannot be default-constructed and assigned.
On the surface of it, no. The conditional operator is an expression (that is, it has a value), while if/else is a statement (thus has no value). They fulfill different "needs" within the language syntax.
However, since you can ignore expression values, and since any expression can be turned into a statement by adding a semicolon, you can essentially emulate if/else with a conditional expression and two auxiliary functions:
// Original code:
if (condition) {
// block 1
}
else {
// block 2
}
// conditional expression replacement:
bool if_block() {
// block 1
return true;
}
bool else_block() {
// block 2
return true;
}
// Here's the conditional expression. bool value discarded:
condition ? if_block() : else_block();
However, having said that, I'm not sure it's anything more than a curiosity...
No, of course not. For reasons already mentioned, and more!
#include <cstdlib>
#include <iostream>
int main()
{
if(int i = std::rand() % 2)
{
std::cout << i << " is odd" << std::endl;
}
else
{
std::cout << i << " is even" << std::endl;
}
}
Check out where is is declared. It's not an often used technique, but it can be used in situations like COM where every call returns HRESULT which is (almost always) zero on success (S_OK), non-zero on failure, so you might write something like:
if(HRESULT hr = myInterface->myMethod())
{
_com_raise_error(hr);
}
The ternary operator can't do anything analogous.
if( cond )
break;
else
a=b;
can not always be replaced by ?: operator. You can often (if not always) rethink your whole code to provide for this substitute, but generally you can't put anything that controls execution into ?:. break, return, loops, throw, etc.
In principle, yes:
if (A) B; else C
becomes
try {
A ? throw TrueResult() : throw FalseResult();
// or: throw A ? TrueResult() : FalseResult();
} catch (TrueResult) {
B;
} catch (FalseResult) {
C;
}
Compared to using procedures (which are more natural), this allows break, continue, return etc. It requires evaluation of A doesn't end with TrueResult/FalseResult but if you use those exceptions only to simulate if, it won't be a problem.
Using the conditional operator results in an expression and both potential results of the conditional operator must be 'compatible' (convertible to the same type).
An if-else construct need not even 'return' any type much less the same one from both branches.
The conditional operator expects to have both of the items following the ? be rvalues (since the result of a conditional operator is itself an rvalue) - so while I'm not entirely an expert on the C/C++ standards, my intuition would be that the following would be disallowed (or failing that, extremely poor coding style...):
(condition) ? return x : return y;
whereas the if-else version would be quite standard:
if(condition) return x;
else return y;
Now, that said, could you take any program and write a similarly functioning program that didn't use if-else? Sure, you probably could. Doesn't mean it would be a good idea, though. ;)
GCC has statement expression, using it you can rewrite if statements to equivalent ?: expressions:
if (<expression>)
<statement1>
else
<statement2>
EDIT: The void casts serves two purpose. The subexpressions in ?: must have the same type, and without the void cast the compiler may print warning: statement with no effect.
(<expression>)? (void)({<statement1>}) : (void)({<statement2>});
I'm currently working with the Diab 4.4 C++ compiler. It's a total POS, non ANSI-compliant, and I've found problems with it in the past.
I'm wondering if the following problem is an issue with the compiler, or a shortcoming in my knowledge of C++
I realize that the form of x = x && y; will short-circuit the y part if x is false. What the compiler is doing is short-circuiting in the case of x = x && y(); where y() is a non-const function.
class A
{
int _a;
A(int a) { _a = a; }
bool someFunction() { _a = 0; return true; }
};
main(...)
{
A obj = A(1);
bool retval = false;
retval = retval && A.someFunction();
/* What is the value of A._a here? */
}
What seems wrong to me is the fact that the compiler is doing this short-circuiting even though someFunction() is not a const function. If it's not const, is the compiler overstepping its bounds by skipping A.someFunction() when retval is false?
Also, I realize this issue can be avoided by writing retval = A.someFunction() && retval; but I'd really like to know why this is happening.
Short circuiting applies to all expressions, regardless of const-ness. Skipping the call to someFunction() is correct.
The && and || operators are defined to evaluate lazily, this is the way the language works. If you want the side effects to always happen, invoke the function first and stash the result, or refactor the function to split the work from the state query.
As others have explained, || and && always perform short-circuit evaluation.
Also note that short-circuit evaluation can be very useful, since it lets you write code like this:
retval = obj_pointer && obj_pointer->SomeBooleanMethod();
Without short-circuit evaluation, this would crash on a NULL pointer.
It doesn't matter if the second operand to && is const or not. After the first operand evaluates to false the return value is known, so there's no reason to evaluate the second operand.
If the function has side effects that require it to be executed, put it first.
Short-circuit evaluation has nothing to do with const or non-const. It happens no matter what.
The statement A() && B(); will do exactly what if (A()) B(); does (although it isn't a perfect substitute, as the second one allows an else). This is sometimes used to change a statement into an expression (such as when writing a macro, or embedding it in another statement).
The && operator is also called the shortcut operator, which means it only evaluates the second part if the first part returned true. That's the main difference between && and &:
value = func1() && func2(); // evaluates func2() only if func1() returns true
value = func1() & func2(); // evaluates both func1() and func2()
For && operator,
1 && X = X
0 && X = 0
so in case first var is 0, compiler will evaluate the expression to 0, no question, what ever the X is.
Compiler will ignore the X part as it wont impact the result. Here X can be any thing function/variable/expression.....