Will a modern compiler automatically optimize the following C++ code? - c++

If i use hte following codes , will the compiler optimize it like a switch structure , which uses a binary tree to search for values ?
if ( X == "aaaa" || X == "bbbb" || X == "cccc" || X == "dddd" )
{
}
else if ( X == "abcd" || X == "cdef" || X == "qqqq" )
{
}
It's just an example , there's no pattern of what's inside the quote symbol
UPDATE
Ok , X is a string , but i don't really think it matters here , i just want to know , when everything inside the if was all about single variable , will it be optimized.

The values WILL be compared one after the other as it is a requirement of the || or, the short-circuit operator. So, here two things will happen:
X will be compared one-by-one from right-to-left.
There will be NO MORE comparisons after any comparison that succeeds (Since it is the short-circuit OR operator) i.e. in the following case
For example:
int hello() {
std::cout<<"Hello";
return 10;
}
int world() {
std::cout<<"World";
return 11;
}
int hello2() {
std::cout<<"Hello2";
return 9;
}
int a = 10;
bool dec = (a == hello() || a == world())
bool dec = (a == hello2() || a == hello() || a == world())
The output for the first statement will be:
Hello
as a == world() will not be executed, and for the second Hello2 Hello, as the comparisons keep on happening till the first success.
In case of the && operator, the comparisons keep on happening until the first failure (as that is enough to determine the outcome of the entire statement).

Almost certainly not. Binary search requires some sort of ordering
relationship, and an ability to compare for less-than. The compiler
cannot assume such exists, and even if it does find one, it cannot
assume that it defines an equivalence relation which corresponds to
==. It's also possible that the compiler can't determine that the
function defining the ordering relationship has no side effects. (If it
has side effects, or if any operation in the expression has side
effects, the compiler must respect the short circuiting behavior of
||.) Finally, even if the compiler did all this... what happens if I
carefully chose the order of the comparisons so that the most frequent
case is the first. Such an “optimization” could even end up
being a pessimization.
The “correct” to handle this is to create a map, mapping the
strings to pointers to functions (or to polymorphic functional objects,
if some state is involved).

It probably depends on the flags you set. Binary trees are faster for search but usually require more code to be handled. So if you optimized for size it probably wont. I'm not sure if it will do it anyway. You know, gcc is optimized according to a LOT of flags. O1, O2, O3, O4 are just simple forms to indicate big groups of flags. You can find a list of all the optimization flags here: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Try to search for strings, binary trees, etc in that page.

Best way to test this is the example like below.
int a = 0;
int b = 0;
if(a == a || b++) {
...
}
cout << b;
value of the b variable should be 0 at the end. b++ part won't be executed. that's the expected behaviour but there might be some exceptions depending on the compiler and its optimization settings. even many scripting langauges like JavaScript behaves this way.

Related

Is if(A | B) always faster than if(A || B)?

I am reading this book by Fedor Pikus and he has some very very interesting examples which for me were a surprise.
Particularly this benchmark caught me, where the only difference is that in one of them we use || in if and in another we use |.
void BM_misspredict(benchmark::State& state)
{
std::srand(1);
const unsigned int N = 10000;;
std::vector<unsigned long> v1(N), v2(N);
std::vector<int> c1(N), c2(N);
for (int i = 0; i < N; ++i)
{
v1[i] = rand();
v2[i] = rand();
c1[i] = rand() & 0x1;
c2[i] = !c1[i];
}
unsigned long* p1 = v1.data();
unsigned long* p2 = v2.data();
int* b1 = c1.data();
int* b2 = c2.data();
for (auto _ : state)
{
unsigned long a1 = 0, a2 = 0;
for (size_t i = 0; i < N; ++i)
{
if (b1[i] || b2[i]) // Only difference
{
a1 += p1[i];
}
else
{
a2 *= p2[i];
}
}
benchmark::DoNotOptimize(a1);
benchmark::DoNotOptimize(a2);
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations());
}
void BM_predict(benchmark::State& state)
{
std::srand(1);
const unsigned int N = 10000;;
std::vector<unsigned long> v1(N), v2(N);
std::vector<int> c1(N), c2(N);
for (int i = 0; i < N; ++i)
{
v1[i] = rand();
v2[i] = rand();
c1[i] = rand() & 0x1;
c2[i] = !c1[i];
}
unsigned long* p1 = v1.data();
unsigned long* p2 = v2.data();
int* b1 = c1.data();
int* b2 = c2.data();
for (auto _ : state)
{
unsigned long a1 = 0, a2 = 0;
for (size_t i = 0; i < N; ++i)
{
if (b1[i] | b2[i]) // Only difference
{
a1 += p1[i];
}
else
{
a2 *= p2[i];
}
}
benchmark::DoNotOptimize(a1);
benchmark::DoNotOptimize(a2);
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations());
}
I will not go in all the details explained in the book why the latter is faster, but the idea is that hardware branch predictor is given 2 chances to misspredict in slower version and in the | (bitwise or) version. See the benchmark results below.
So the question is why don't we always use | instead of || in branches?
Is if(A | B) always faster than if(A || B)?
No, if(A | B) is not always faster than if(A || B).
Consider a case where A is true and the B expression is a very expensive operation. Not doing the operation can save that expense.
So the question is why don't we always use | instead of || in branches?
Besides the cases where the logical or is more efficient, the efficiency is not the only concern. There are often operations that have pre-conditions, and there are cases where the result of the left hand operation signals whether the pre-condition is satisfied for the right hand operation. In such case, we must use the logical operator.
if (b1[i]) // maybe this exists somewhere in the program
b2 = nullptr;
if(b1[i] || b2[i]) // OK
if(b1[i] | b2[i]) // NOT OK; indirection through null pointer
It is this possibility that is typically the problem when the optimiser is unable to replace logical with bitwise. In the example of if(b1[i] || b2[i]), the optimiser can do such replacement only if it can prove that b2 is valid at least when b1[i] != 0. That condition might not exist in your example, but that doesn't mean that it would necessarily be easy or - sometimes even possible - for the optimiser to prove that it doesn't exist.
Furthermore, there can be a dependency on the order of the operations, for example if one operand modifies a value read by the other operation:
if(a || (a = b)) // OK
if(a | (a = b)) // NOT OK; undefined behaviour
Also, there are types that are convertible to bool and thus are valid operands for ||, but are not valid operators for |:
if(ptr1 || ptr2) // OK
if(ptr1 | ptr2) // NOT OK; no bitwise or for pointers
TL;DR If we could always use bitwise or instead of logical operators, then there would be no need for logical operators and they probably wouldn't be in the language. But such replacement is not always a possibility, which is the reason why we use logical operators, and also the reason why optimiser sometimes cannot use the faster option.
If evaluating A is fast, B is slow, and when the short circuit happens (A returns true), then if (A || B) will avoid the slow path where if (A | B) will not.
If evaluating A almost always gives the same result, the processor's branch prediction may give if (A || B) performance better than if (A | B) even if B is fast.
As others have mentioned, there are cases where the short circuit is mandatory: you only want to execute B if A is known to evaluate false:
if (p == NULL || test(*p)) { ... } // null pointer would crash on *p
if (should_skip() || try_update()) { ... } // active use of side effects
Bitwise-or is a branchless arithmetic operator corresponding to a single ALU instruction. Logical-or is defined as implying shortcut evaluation, which involves a (costly) conditional branch. The effect of the two can differ when the evaluations of the operands have side effects.
In the case of two boolean variables, a smart compiler might evaluate logical-or as a bitwise-or, or using a conditional move, but who knows...
So the question is why don't we always use | instead of || in branches?
Branch prediction is relevant only to fairly hot pieces of code, and it depends on the branch being predictable enough to matter. In most places, | has little or no performance benefit over ||.
Also, taking A and B as expressions of suitable type (not necessarily single variables), key relevant differences include:
In A || B, B is evaluated only if A evaluates to 0, but in A | B, B is always evaluated. Conditionally avoiding evaluation of B is sometimes exactly the point of using the former.
In A || B there is a sequence point between evaluation of A and evaluation of B, but there isn't one in A | B. Even if you don't care about short-circuiting, you may care about the sequencing, even in relatively simple examples. For example, given an integer x, x-- || x-- has well-defined behavior, but x-- | x-- has undefined behavior.
When used in conditional context, the intent of A || B is clear to other humans, but the reason to substitute A | B less so. Code clarity is extremely important. And after all, if the compiler can see that it is safe to do so (and in most cases it is more reliable than a human at making the determination) then it is at liberty to compile one of those expressions as if it were the other.
If you cannot be sure that A and B both have built-in types -- in a template, for example -- you have to account for the possibility that one or both of | and || have been overloaded. In that case, it is reasonable to suppose that || will still do something that makes sense for branch control, but it is much less safe to assume that | will do something equivalent or even suitable.
As an additional minor matter, the precedence of | is different from that of ||. This can bite you if you rely on precedence instead of parentheses for grouping, and you need to watch out for that if you are considering modifying existing code to change || expressions to | expressions. For example, A && B || C && D groups as (A && B) || (C && D), but A && B | C && D groups as (A && (B | C)) && D.
Even if a and b are automatic-duration Boolean flags, that doesn't mean that an expression like a||b will be evaluated by checking the state of one flag, and then if necessary checking the state of the other. If a section of code performs:
x = y+z;
flag1 = (x==0);
... code that uses flag1
a compiler could replace that with:
x = y+z;
if (processor's Z flag was set)
{
... copy of that uses flag1, but where flag is replaced with constant 1
}
else
{
... copy of that uses flag1, but where flag is replaced with constant 0
}
Although hardly required to do so, a compiler may base some of its decisions about whether to perform such substitution upon a programmer's choice of whether ot write (flag1 || flag2) or (flag1 | flag2), and many factors may cause the aforementioned substitution to run faster or slower than the original code.
Code readability, short-circuiting and it is not guaranteed that Ord will always outperform a || operand.
Computer systems are more complicated than expected, even though they are man-made.
There was a case where a for loop with a much more complicated condition ran faster on an IBM. The CPU didn't cool and thus instructions were executed faster, that was a possible reason. What I am trying to say, focus on other areas to improve code than fighting small-cases which will differ depending on the CPU and the boolean evaluation (compiler optimizations).
The expression A | B might be faster in a loop that the compiler can optimize to a bitwise or of two vectors. Another case where | might be slightly more optimized is when the compiler would want to optimize away a branch by combining the two operands with bitmasks. If the operand on the right is something that might have visible side-effects, the compiler must instead insert a branch to guarantee the correct short-circuiting.
In other situations I can think of, A || B will be as fast or faster, including just about all the ones I can think of where you’re comparing a single pair of operands rather than a vector. However, those are almost never critical to performance.
Adding to the list:
Given the case that A and B are totally unpredictable, but usually A||B is true (i.e. when A is wrong, then usually B is true and vice versa).
In this case A||B may lead to a lot of mispredictions, but A|B is predictable and most likely faster.
So the question is why don't we always use | instead of || in branches?
In my little mind three reasons, but that might be only me.
First and most: all code tends to be read multiple times more often than it is written. So, in the example you have an array of ints with value either zero or 1. What the code really is meant to do is hidden to the reader. It might be clear to the original writer exactly what is supposed to be done, but years later, and after adding lots and lots of code lines it is probably anyones guess. In my world use what shows the intended comparison, it either is a bit comparison or a logical one. It should not be both.
Secondly: does the performance gain really matter? The example basically does nothing and could be coded a lot more efficient. Not? Well don't create the array in the first place, what the code does now is simply to check the quality of the rand function. The optimization is an example where a better analysis of the problem probably would give a much larger gain.
Third: a different compiler or a different processor will probably change the relative speeds. Now, what you are doing here is applying your knowledge of the internals of the current compiler and current processor. Next version of compiler and processor might turn the question around totally. You really cannot know. And we all know that the only way to know if an optimization actually will be quicker is by testing, which this very specific example has done.
So, if, for some reason, getting the very last bit of efficiency out of the code is worth it I would mark the choice as a "hack". I would probably include a macro with something like "DO_PERFORMANCE_HACKS" and have two versions of the code, one with | and one with || and commenting what the intention is. By changing the macro it will be possible for next readers to see what and where the hack is, and in the future may elect to not compile them.

Ternary Operator Not Generating Error

I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.

breaking up conditional expression

I'm trying to evaluate if there's a performance hit in writing this expression
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
as
bool func() {
if (expr1)
return 1;
if (expr2)
return 1;
...
if (exprN)
return 1;
return 0;
}
The reason I'm trying to do the latter is simply to improve readability/maintainability (eg. latter can be written in terms of a helper macro and thereby making it easier to add/remove exprs. There are about 50 expressions in this case).
A similar scenario is writing
bool func() {
if (expr1 && expr2 && ... && exprN) {
return 1;
}
return 0;
}
as
bool func() {
if (!expr1) {
return 0;
}
if (!expr2) {
return 0;
}
...
if (!exprN) {
return 0;
}
return 1;
}
Is there a performance hit in this case and if so do compilers optimize try to optimize it? I'd be interested to know if gcc does that.
(To give some context the expressions themselves are functions and let's say we want to determine if all or at least one returns true. The functions take arguments of different types)
Your two versions are functionally equivalent.
In C/C++ (and many other languages) the logical operators || and && perform "short-circuit" evaluation. They evaluate the sub-expressions from left to right, stopping as soon as the result is known. In the case of ||, this means it stops as soon as it gets a true (non-zero) result (because true || anything is true); in the case of &&, it stops as soon as it gets a false (zero) result (because false && anything is false).
If you were performing any other actions in your if bodies other than just returning from the function, it would be duplicated for every expression that's true. But since you're returning from the function as soon as one of the expressions is true, you'll never test any of the remaining expressions. So it's doing the same short-circuiting.
If you did have some action in the body, you could get the same type of short-circuiting by using else if rather than if. However, this would violate the DRY principle. But if it's in the output of a macro, rather than the original source code, this wouldn't be a signficant concern (although it would likely increase the size of the generated code -- if taken to extremes this could have memory performance implications).
Your current code
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
involving umpteen logical expressions, can be written as the possibly more clear & maintainable
auto func()
-> bool
{
return false
|| expr1
|| expr2 ...
|| exprN;
}
This allows the compiler the best opportunity to optimize, because it's presented with complete information about the desired effect.
In contrast, a series of individual if statements would have to be analyzed by the compiler to determine that they implement an OR-chain.
As always when in doubt about micro-performance, MEASURE.
The C and C++ codes are generated to its assembly equivalent.
Hence, what i think is that the code generated should not be different unless you have multiple output function or jump statements(including Return, like you have in your second example).
So i think there should be no performance hit unless you have too many jumps in your improved readability code.

What's the point of the NOT operator? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
Currently checking out C++ using this tutorial. It explains what the ! NOT operator is, kind of, but I don't think I fully understand why I'd ever want to use it. Can someone please explain?
The ! operator is useful if you want to check that a condition is not currently satisfied.
Imagine a function that tells you if a particular subsystem of your application was initialized and another function to initialize it:
bool subsystem_is_initialized();
void subsystem_initialize();
You could check that it was initialized and initialize it if it wasn't using the not operator.
if (!subsystem_is_initialized())
subsystem_initialize();
For all practical purposes, it's a shorter way to compare a value to zero, with an explicit suggestion that the affected value is boolean. You don't absolutely need it, but then again, neither do you need multiplications (you can loop over an addition), additions (you can do it with binary logic), or most of binary logic (you can do pretty much anything with NANDs, I've been told, but I haven't researched it myself).
Also keep in mind that, like almost all other C++ operators, it can be overloaded by classes.
A language is not always (in fact as good as never) defined to have the minimal set of features but a set of features that useful. For example, if you had the following code:
if (!test_something())
do_something();
You could also express this as
if (test_something()) {
} else
do_something();
but it would be less easy to read. So, while logical negation can usually be expressed by other constructs of the C++ language, it helps readability to express negation explicitly to indicate your intent.
It's used when you need to flip a true/false in a condition, to increase readability.
e.g.
Compare
// Ensure that the thing is NOT red.
if (thing_is_red() == false)
...
if (!thing_is_red())
...
Okay, you want to divide the sum of two numbers to a third one, so you can do this if the third number is not zero.
#include <iostream>
using namespace std;
int main()
{
int a,b,c,sum;
cin >> a >> b >> c;
sum = a+b;
if (c!=0) //which is equivalent to if(!c)
cout << sum/c;
}
I used an easy example in order to understand it quickly. Is everything okay now? Regards and good luck with your study.
! or the NOT operator is the logical equivalent of a NOT gate.
So, a NOT gate truth table says if x is true, then !x is false. and vice-versa.
Not too difficult if you think of it logically. For example NOT of male is a female, NOT true is false, NOT simple is complex..
The most frequent case is probably with an std::istream:
int i;
std::cin >> i;
if ( ! std::cin ) {
// Something went wrong...
}
Other than that, all sorts of classes have isValid() or
isDone() functions; to iterate using a GoF iterator, for
example:
for ( IteratorType i( init ); ! i.isDone(); i.next() ) {
// Do something with i.element()
}
Map classes often have a contains function, so you might ask
if ( ! myMap.contains( key ) )
You'll also use boolean variables from time to time: for
a linear search where the match condition requires some
complicated evaluation, for example:
bool found = false;
int current = 0;
while ( ! found && current != end ) {
// maybe set found...
}
The tutorial you mention:
NOT: The NOT operator accepts one input. If that input is TRUE, it returns FALSE, and if that input is FALSE, it returns TRUE.
it means NOT operator is unary operator means single operand(not a binary operator)
like && and||` are binary operators and there syntax is:
result = operand1 && operand2
result = operand1 || operand2
Unary is:
result = !operand1
and its result values is revert of operand value id operand1 = True then result would be False and if operand1 = False result is True.
same is written there:
For example, NOT (1) evaluates to 0, and NOT (0) evaluates to 1. NOT (any number but zero) evaluates to 0. In C and C++ NOT is written as !. NOT is evaluated prior to both AND and OR.
in c/c++ 0 is False and
Non 0 is equivalent to True.
there is couple of good examples too!
(1).
!( 1 || 0 )
We know 1 || 0 is 1 means true and application of NOT operator makes it 0 means False:
!( 1 || 0 )
=> ! (1)
=> 0 that is false
Do you notice in this expression we have two operators logical || or and ! NOT operator.
!( 1 || 0 )
^ ^
NOT OR
and notice for OR operator || there is two operands bit single for unary NOT
! operator is used for negation purpose in bool condition checks. There are many places you can use it. Simple example:
if (!existInArray(A, i))
check if i is NOT exist in array.
The point of the ! operator is to make an expression that is false into a true expression. It is most often used as a replacement for == false or == 0. It often makes the expression easier to read:
if (p == NULL || p->next != NULL)
is the same as :
if (!p || p->next)
[Ok, so "easier to read" here is obviously quite subjective].
You have quite a number of answers explaining the NOT operator.
I am not a big fan of the ! operator myself. It is not nearly as visible as it should be (in that, it reverses the meaning of the clause).
For example, despite several years of programming in C++, it still takes me several seconds to parse if ( ! ptr ) as opposed to if ( ptr == NULL ) which instantly conveys me its meaning.
Does if ( ! (i % 2) ) check for even or odd numbers? If you didn't have the answer after your eyes went past the '?', and/or had to review the if condition again, you have just made my case.
Reviewing posts, I agree with some of the posters that the NOT operator has valid uses when applied to bools and function calls. Using ! while processing streams is considered idiomatic.
That said, nearly every programmer I know has been bitten by strcmp. I worked in a shop that has a few #defines such as #define STRCMP_EQUAL 0 etc., and required the check to be written as if ( STRCMP_EQUAL == strcmp(str1, str2) ) which, in my opinion, is orders of magnitude more explicit than if ( ! strcmp(str1, str2) ).
! operator could be used with user defined datatypes(classes and structs in c++).
like every operator(expect . : and ::) !operator could be overloaded. See the following scenario.
//A is empty if memeber size is 0, and no further operations are allowed on other members if
// class is empty.
class A{
int size;
int lot;
int price;
public:
bool operator!()
{
if(lot)
return true;
else
return false;
}
};
A AObj;
//Aobj has size greater than 0
if(!Aobj)
{
//code to Fill or reuse the object.
}
The point of the ! operator is to make an expression that is false into a true expression. It is most often used as a replacement for == false or == 0. It often makes the expression easier to read:
if (p == NULL || p->next != NULL)
is the same as :
if (!p || p->next)
[Ok, so "easier to read" here is obviously quite subjective].

Using bitwise operators for Booleans in C++

Is there any reason not to use the bitwise operators &, |, and ^ for "bool" values in C++?
I sometimes run into situations where I want exactly one of two conditions to be true (XOR), so I just throw the ^ operator into a conditional expression. I also sometimes want all parts of a condition to be evaluated whether the result is true or not (rather than short-circuiting), so I use & and |. I also need to accumulate Boolean values sometimes, and &= and |= can be quite useful.
I've gotten a few raised eyebrows when doing this, but the code is still meaningful and cleaner than it would be otherwise. Is there any reason NOT to use these for bools? Are there any modern compilers that give bad results for this?
|| and && are boolean operators and the built-in ones are guaranteed to return either true or false. Nothing else.
|, & and ^ are bitwise operators. When the domain of numbers you operate on is just 1 and 0, then they are exactly the same, but in cases where your booleans are not strictly 1 and 0 – as is the case with the C language – you may end up with some behavior you didn't want. For instance:
BOOL two = 2;
BOOL one = 1;
BOOL and = two & one; //and = 0
BOOL cand = two && one; //cand = 1
In C++, however, the bool type is guaranteed to be only either a true or a false (which convert implicitly to respectively 1 and 0), so it's less of a worry from this stance, but the fact that people aren't used to seeing such things in code makes a good argument for not doing it. Just say b = b && x and be done with it.
Two main reasons. In short, consider carefully; there could be a good reason for it, but if there is be VERY explicit in your comments because it can be brittle and, as you say yourself, people aren't generally used to seeing code like this.
Bitwise xor != Logical xor (except for 0 and 1)
Firstly, if you are operating on values other than false and true (or 0 and 1, as integers), the ^ operator can introduce behavior not equivalent to a logical xor. For example:
int one = 1;
int two = 2;
// bitwise xor
if (one ^ two)
{
// executes because expression = 3 and any non-zero integer evaluates to true
}
// logical xor; more correctly would be coded as
// if (bool(one) != bool(two))
// but spelled out to be explicit in the context of the problem
if ((one && !two) || (!one && two))
{
// does not execute b/c expression = ((true && false) || (false && true))
// which evaluates to false
}
Credit to user #Patrick for expressing this first.
Order of operations
Second, |, &, and ^, as bitwise operators, do not short-circuit. In addition, multiple bitwise operators chained together in a single statement -- even with explicit parentheses -- can be reordered by optimizing compilers, because all 3 operations are normally commutative. This is important if the order of the operations matters.
In other words
bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false
will not always give the same result (or end state) as
bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler
This is especially important because you may not control methods a() and b(), or somebody else may come along and change them later not understanding the dependency, and cause a nasty (and often release-build only) bug.
The raised eyebrows should tell you enough to stop doing it. You don't write the code for the compiler, you write it for your fellow programmers first and then for the compiler. Even if the compilers work, surprising other people is not what you want - bitwise operators are for bit operations not for bools.
I suppose you also eat apples with a fork? It works but it surprises people so it's better not to do it.
I think
a != b
is what you want
Disadvantages of the bitlevel operators.
You ask:
“Is there any reason not to use the bitwise operators &, |, and ^ for "bool" values in C++? ”
Yes, the logical operators, that is the built-in high level boolean operators !, && and ||, offer the following advantages:
Guaranteed conversion of arguments to bool, i.e. to 0 and 1 ordinal value.
Guaranteed short circuit evaluation where expression evaluation stops as soon as the final result is known.
This can be interpreted as a tree-value logic, with True, False and Indeterminate.
Readable textual equivalents not, and and or, even if I don't use them myself.
As reader Antimony notes in a comment also the bitlevel operators have alternative tokens, namely bitand, bitor, xor and compl, but in my opinion these are less readable than and, or and not.
Simply put, each such advantage of the high level operators is a disadvantage of the bitlevel operators.
In particular, since the bitwise operators lack argument conversion to 0/1 you get e.g. 1 & 2 → 0, while 1 && 2 → true. Also ^, bitwise exclusive or, can misbehave in this way. Regarded as boolean values 1 and 2 are the same, namely true, but regarded as bitpatterns they're different.
How to express logical either/or in C++.
You then provide a bit of background for the question,
“I sometimes run into situations where I want exactly one of two conditions to be true (XOR), so I just throw the ^ operator into a conditional expression.”
Well, the bitwise operators have higher precedence than the logical operators. This means in particular that in a mixed expression such as
a && b ^ c
you get the perhaps unexpected result a && (b ^ c).
Instead write just
(a && b) != c
expressing more concisely what you mean.
For the multiple argument either/or there is no C++ operator that does the job. For example, if you write a ^ b ^ c than that is not an expression that says “either a, b or c is true“. Instead it says, “An odd number of a, b and c are true“, which might be 1 of them or all 3…
To express the general either/or when a, b and c are of type bool, just write
(a + b + c) == 1
or, with non-bool arguments, convert them to bool:
(!!a + !!b + !!c) == 1
Using &= to accumulate boolean results.
You further elaborate,
“I also need to accumulate Boolean values sometimes, and &= and |=? can be quite useful.”
Well, this corresponds to checking whether respectively all or any condition is satisfied, and de Morgan’s law tells you how to go from one to the other. I.e. you only need one of them. You could in principle use *= as a &&=-operator (for as good old George Boole discovered, logical AND can very easily be expressed as multiplication), but I think that that would perplex and perhaps mislead maintainers of the code.
Consider also:
struct Bool
{
bool value;
void operator&=( bool const v ) { value = value && v; }
operator bool() const { return value; }
};
#include <iostream>
int main()
{
using namespace std;
Bool a = {true};
a &= true || false;
a &= 1234;
cout << boolalpha << a << endl;
bool b = {true};
b &= true || false;
b &= 1234;
cout << boolalpha << b << endl;
}
Output with Visual C++ 11.0 and g++ 4.7.1:
true
false
The reason for the difference in results is that the bitlevel &= does not provide a conversion to bool of its right hand side argument.
So, which of these results do you desire for your use of &=?
If the former, true, then better define an operator (e.g. as above) or named function, or use an explicit conversion of the right hand side expression, or write the update in full.
Contrary to Patrick's answer, C++ has no ^^ operator for performing a short-circuiting exclusive or. If you think about it for a second, having a ^^ operator wouldn't make sense anyway: with exclusive or, the result always depends on both operands. However, Patrick's warning about non-bool "Boolean" types holds equally well when comparing 1 & 2 to 1 && 2. One classic example of this is the Windows GetMessage() function, which returns a tri-state BOOL: nonzero, 0, or -1.
Using & instead of && and | instead of || is not an uncommon typo, so if you are deliberately doing it, it deserves a comment saying why.
Patrick made good points, and I'm not going to repeat them. However might I suggest reducing 'if' statements to readable english wherever possible by using well-named boolean vars.For example, and this is using boolean operators but you could equally use bitwise and name the bools appropriately:
bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
.. stuff ..
}
You might think that using a boolean seems unnecessary, but it helps with two main things:
Your code is easier to understand because the intermediate boolean for the 'if' condition makes the intention of the condition more explicit.
If you are using non-standard or unexpected code, such as bitwise operators on boolean values, people can much more easily see why you've done this.
EDIT: You didnt explicitly say you wanted the conditionals for 'if' statements (although this seems most likely), that was my assumption. But my suggestion of an intermediate boolean value still stands.
Using bitwise operations for bool helps save unnecessary branch prediction logic by the processor, resulting from a 'cmp' instruction brought in by logical operations.
Replacing the logical with bitwise operations (where all operands are bool) generates more efficient code offering the same result. The efficiency ideally should outweigh all the short-circuit benefits that can be leveraged in the ordering using logical operations.
This can make code a bit un-readable albeit the programmer should comment it with reasons why it was done so.
IIRC, many C++ compilers will warn when attempting to cast the result of a bitwise operation as a bool. You would have to use a type cast to make the compiler happy.
Using a bitwise operation in an if expression would serve the same criticism, though perhaps not by the compiler. Any non-zero value is considered true, so something like "if (7 & 3)" will be true. This behavior may be acceptable in Perl, but C/C++ are very explicit languages. I think the Spock eyebrow is due diligence. :) I would append "== 0" or "!= 0" to make it perfectly clear what your objective was.
But anyway, it sounds like a personal preference. I would run the code through lint or similar tool and see if it also thinks it's an unwise strategy. Personally, it reads like a coding mistake.