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.....
Related
I saw some C++ code like this:
bool MyProject::boo(...)
{
bool fBar = FALSE;
....
return !!fBar;
}
I couldn't think of any difference between returning fBar directly in this case and returning !!fBar. How two negatives make a difference?
Thank you
In your example, there's no difference between returning fBar and returning !!fBar.
In other cases, e.g. when a user-defined type such as BOOL (typedef-ed to be int) is used, the !! construct has the effect of coercing any non-zero value to true; i.e. !!fBar is equivalent to fBar ? true : false. This can make a difference if fBar can be 5 and you want to compare it against TRUE, which is defined to be (BOOL)1.
This is typically done to avoid compiler warnings in situations when a non-bool value has to be converted to bool type. Some compilers (like MSVC++) issue a "performance" warning when a non-bool value is implicitly converted to bool. One way to suppress this warning is to use an explicit conversion. Another way is to use the !! combination.
However, in your case the argument of return is already declared as a bool, meaning that the above reasoning does not apply. (Are you sure it was bool and not, say, BOOL?). In that case there's no meaningful explanation for that !!.
!! "is" "to boolean" operator (not really, it is two negate operators). It make no different is this case. However, it will make difference if is not bool.
e.g.
int fBar = 2; // !!fBat evaluate to 1
bool b = (fBar == true) // this is false
b = fBar; // this is true
b = !!fBar; // this is also true
typedef int MyBool; // say some library use int as boolean type
#define MY_TRUE 1
#define MY_FALSE 0
MyBool b2 = fBar; // this evaluate to true, but not equal to true
if (b2 == MY_TRUE )
{
// this code will not run, unexpected
}
if (b2)
{
// this code will run
}
MyBool b3 = !!fBar;
if (b2 == MY_TRUE )
{
// this code will run
}
if (b2)
{
// this code will run
}
Let's say I had two functions and a variable,
int number;
bool foo (void);
bool footoo (void);
And in each of these functions, some logic with the variable number takes place, such as:
number++;
return(rand()%2);
And then I call them like so:
if (foo() && footoo())
{
cout << "Two foo true!"
}
Why aren't both functions being called and how can I guarantee both functions are called and increment number, regardless of return value?
In C (and included in C++ by default) the && operator is short-circuiting. This means that as soon as the condition is deemed false the other operand is not evalulated. It allows us to do things like if(ptr && ptr->value == 10) without having to do the pointer validity check before the value check in a separate if statement.
If you want to run both functions, run both functions and save off the results:
bool b = foo();
if(foobar() && b)
{
// Stuff
}
Simplest thing I can think of: Assign the return values of both to variables and check those:
bool fooIsTrue = foo();
bool footooIsTrue = footoo();
if(fooIsTrue && footooIsTrue)
// ...
They aren't being called right now because && short-circuits, that is, when the left is false the whole expression is sure to be false so the right side is skipped.
This is useful for constructions where for example you want to first check if you can access something before you check it like so:
if(somePtr != NULL && somePtr[0] == 1)
Why aren't both functions being called? It's called "short-circuit evaluation" and is an efficiency feature of C++. The rationale (roughly) is that code called in the context of a test is generally side-effect-free, and therefore if you can establish that the test is going to fail by only evaluating the leftmost expression, you should do so.
Your code is not side-effect-free, so short-circuit evaluation is not a feature that helps you in this case.
In order to guarantee both functions are called, you'll need to call them separately from the test of their return values:
bool fooRet = foo();
bool footooRet = footoo();
if (fooRet && footooRet)
{
cout << "Two foo true!"
}
In an if statement where && is involved (something like if (a && b && c && d)), if the 1st condition is false, then the rest of the condition in the if isn't evaluated anymore and the false "block" is executed.
The same thing happens with ||. If you have if (a || b || c || d) and a is true, then the rest of the condition isn't evaluated and the true "block" is executed.
If you want both of them to be called, just assign them to two boolean variables like bool myB1 = foo(), myB2 = footoo(); and then do if (myB1 && myB2).
&& and || are what we call short circuit operators. What this means is that if by evaluating the first argument we can tell the truthiness of the whole expression we stop and don't evaluate the next expression.
For example if in this statement a && b is a is false we know the whole statement cannot be true and thus it is ok to stop. With || we can stop if the first statement is true.
If you want both functions to be called the first one must return a value that can be evaluated as true. You can do this if you want both to be called.
bool a = foo();
bool b = footoo();
if (a && b)
{
cout << "Two foo true!"
}
This way both are called.
In C++ bool's are guaranteed to be a 1 or 0 so the bitwise operators are actually the same as the short circuit it terms of the result. However I would not use them for readability.
Becasue with statement if(first && second) , if first is not true, second is not even checked.
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.
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.
Until now I was thinking the conditional operator int a = b == 2 ? x1 : x2; is always replaceable by an if/else statement.
int a;
if (b == 2)
a = x1;
else
a = x2;
And the choice between one of the two is always a matter of taste. Today I was working with a task where a reference would be useful if I could write:
int& a;
if (b == 2)
a = x1;
else
a = x2;
This is not allowed and I tried the initialization of the reference with the conditional operator. This was working and I came to realize, that the conditional operator is not always replaceable by an if/else statement.
Am I right with this conclusion?
You are correct. The conditional operator is an expression, whereas if-else is a statement. An expression can be used where a statement can be used, but the opposite is not true.
This is a good counterexample to show when you come across somebody who insists that you should never, never, never, ever use conditional expressions, because if-else is "simple" and conditionals are "too complicated".
When C++ gets lambda expressions, then you may be able to use a lambda with an if-else in place of a conditional.
Well, there are obviously lots of places that you can't place an if. For example:
func( x ? 0 : 1 );
There is no way of writing that with an if statement. And this is a dupe, several times, not that I blame you for not finding it, because I can't.
Not exactly. You can always replace the reference (not re-seatable) with a pointer (re-seatable). So it's a matter of context.
E.g. you can write
int* pa;
if( b == 2 )
pa = &x1;
else
pa = &x2;
int& a = *pa;
No problemo, as someone once remarked to the Terminator.
And going all out for maximum "ugh what's that" effect,
int* pa;
switch( b == 2 )
{
case true:
pa = &x1; break;
default:
pa = &x2;
}
int& a = *pa;
But it's more clear with the conditional operator in this case. :-)
int& a = (b == 2? x1 : x2);
Cheers & hth.,
You are going to have more problems than that
// works
ostream *o;
if(x)
o = &myfiles;
else
o = &mystrings;
// stringstream* and fstream* -- incompatible!
ostream *o = x ? &myfiles : &mystrings;
You are right.
In C++ there are conditional assignment situations where use of the if-else statement is impossible, since this language explicitly distinguishes between initialization and assignment.
Furthermore, the ternary operator can yield an lvalue, i.e. a value to which another value can be assigned.
Also, some compilers in some cases may generate different code for ternary vs conditional if-then. GCC, for example, performs better code optimization if ternary operator is used.
See also ?: ternary operator in C++.
You can't use it directly, but you can always get around that restriction by turning your conditional into something that is evaluated as an expression...
int& initValue(int b, int& x1, int& x2){
if (b==2)
return x1;
return x2;
}
...
int& a = initValue(b, x1, x2);
Of course, this may be overkill for ints.
It depends on your definition of replaceable. For example, within a single function call, I cannot replace the following conditional operator with an if-else.
int n1 = 10;
int n2 = 20;
const int& i = x > 0 ? n1 : n2;
However, with the addition of another function, I've effectively replaced the conditional operator with an if-else.
const int& get_i(double x)
{
if(x > 0)
return n1;
else
return n2;
}
int main()
{
const int& i = get_i(x);
}
Acording to kodify.net we cannot replace every if/else statement with the conditional operator. There are two requirements for doing so: there must be one expression in both the if and the else block.