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].
Related
I was messing around with some c++ code after learning that you cannot increment booleans in the standard. I thought incrementing booleans would be useful because I like compacting functions if I can and
unsigned char b = 0; //type doesn't really matter assuming no overflow
while (...) {
if (b++) //do something
...}
is sometimes useful to have, but it would be nice to not have to worry about integer overflow. Since booleans cannot take on any value besides 0 or 1, I thought that perhaps this would work. Of course, you could just have a boolean assigned to 1 after you do your operation but that takes an extra line of code.
Anyway, I thought about how I might achieve this a different way and I came up with this.
bool b = 0;
while (...)
if (b & (b=1)) ...
This turned out to always evaluate to true, even on the first pass through. I thought - sure, its just doing the bitwise operator from right to left, except that when I swapped the order, it did the same thing.
So my question is, how is this expression being evaluated so that it simplifies to always being true?
As an aside, the way to do what I wanted is like this I guess:
bool b = 0;
while (...) if (!b && !(b=1)) //code executes every time except the first iteration
There's a way to get it to only execute once, also.
Or just do the actually readable and obvious solution.
bool b = 0;
while (...) {
if (b) {} else {b=1;}
}
This is what std::exchange is for:
if (std::exchange(b, true)) {
// b was already true
}
As mentioned, sequencing rules mean that b & (b=1) is undefined behaviour in both C and C++. You can't modify a variable and read from it "without proper separation" (e.g., as separate statements).
There is no "strange behavior" here. The & operator, in your case is a bitwise arithmetic operator. These operator are commutative, so both operand must be evaluated before computing the resulting value.
As mentioned earlier, this is considered as undefined behavior, as the standard does not prevent computing + loading into a register the left operand, before doing the same to the second, or doing so in reverse order.
If you are using C++14 or above, you could use std::exchange do achieve this, or re-implement it quite easily using the following :
bool exchange_bool(bool &var, bool &&val) {
bool ret = var;
var = val;
return ret;
}
If you end up re-implementing it, consider using template instead of hard-coded types.
As a proper answer to your question :
So my question is, how is this expression being evaluated so that it simplifies to always being true?
It does not simplify, if we strictly follow the standard, but I'd guess you are always using the same compiler, which end up producing the same output.
Side point: You should not "compact" functions. Most of the time the price of this is less readability. This might be fine if you're the only dev working on a project, but on bigger project, or if you come back to your code later, that could be an issue. Last but not least, "compact" function are more error prone, because of their lack of readability.
If you really want shorter function, you should consider using sub-function that will handle part of the function computation. This would enable you to write short function, to quickly fix or update behavior, without impacting clarity.
I don't see what meaning you can assign to a "bitwise increment" operator. If I am right, what you achieve is just setting the low-order bit, which is done by b|= 1 (following the C conventions, this could have been defined as a unary b||, but the || was assigned another purpose). But I don't feel that this is a useful bitwise operation, and it can increment only once. IMO the standard increment operator is more bitwise.
If your goal was in fact to "increment" a boolean variable, i.e. set it to true (prefix or postfix), b= b || true is a way. (There is no "logical OR assignement" b||= true, and even less a "logical increment" b||||.)
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to check for equals? (0 == i) or (i == 0)
Why does one often see “null != variable” instead of “variable != null” in C#?
Why do some experienced programmers write expressions this way?
What is the meaning of NULL != value in C++?
For example,
int k =5;
if( 5 == k )
{
}
is preferred over
if (k == 5)
{
}
Is it considered only for formatting purpose or is there any reason behind it?
Because that form makes it harder to introduce a bug by forgetting one of the equals signs. Imagine if you did this:
if (k = 5)
This was intended as a comparison, but it's now an assignment! What's worse, it is legal, and it will mess up your program in multiple ways (the value of k is changed, and the conditional always evaluates to true).
Contrast this with
if (5 = k)
This is not legal (you cannot assign to a literal) so the compiler will immediately flag it as an error.
That said, this style of writing code (assignments within conditionals) is not as prevalent today as it once was. Most modern compilers will flag this as a warning, so it's unlikely to go undetected. Personally I don't like the second form and since the compiler is there to help I don't use it.
If you mistype and write
if (k = 5) // instead of ==
then you likely just introduced a hard to find bug. (Actually, it used to be hard to find. Nowadays, most compilers will flag this as a warning.)
This, however, will result in a compile-time error
if (5 = k)
BTW, this style is called Yoda Conditions :-)
It's to avoid the mistake of
if( k = 5 ) {
}
which would always equal true.
A. Who said it's preferred ?!
the only reason i can think of it's to avoid:
int k =5;
if( 5 = k )//notice one "="
{
}
like this you will get a compilation error, while the other way will work. but I think it's less readable and less preferred.
First of all, most people prefer the second form, since it feels "more natural"; the first form is felt as "reversed", and in fact is often called "Yoda conditional".
The rationale behind using the first form is to avoid accidental assignment when typing = instead of == by error. Since in a conditional you can write any expression, = is allowed, so in case of mistyping the instruction
if(k = 5)
{
}
won't check if k is equal to 5, but will assign 5 to k and, since = returns a reference to its left hand operator, the condition will be evaluated as true and the if body will always be executed.
On the other hand, if you typed = instead of == in the Yoda conditional you would get
if(5 = k)
{
}
which results in a compilation error, since you can't assign anything to a literal (5).
Although they look like a good idea, "Yoda conditionals" are quite weird looking, and, most importantly, almost any good compiler with warnings turned on will warn you anyway if you write an assignment inside a conditional expression, so most people just use the "natural looking" form.
It's because a common typo is typing = instead of ==.
& has &&. | has ||. Why doesn't ^ have ^^?
I understand that it wouldn't be short-circuiting, but it would have different semantics. In C, true is really any non-zero value. Bitwise XOR is not always the same thing as logical XOR:
int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)
Since you can't always rely on a true value being 1 or -1, wouldn't a ^^ operator be very helpful? I often have to do strange things like this:
if(!!a ^ !!b) // looks strange
Dennis Ritchie answers
There are both historical and practical reasons why there is no ^^ operator.
The practical is: there's not much use for the operator. The main point of && and || is to take advantage of their short-circuit evaluation not only for efficiency reasons, but more often for expressiveness and correctness.
[...]
By contrast, an ^^ operator would always force evaluation of both arms of the expression, so there's no efficiency gain. Furthermore, situations in which ^^ is really called for are pretty rare, though examples can be created. These situations get rarer and stranger as you stack up the operator--
if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
does the consequent exactly when an odd number of the condx()s are true. By contrast, the && and || analogs remain fairly plausible and useful.
Technically, one already exists:
a != b
since this will evaluate to true if the truth value of the operands differ.
Edit:
Volte's comment:
(!a) != (!b)
is correct because my answer above does not work for int types. I will delete mine if he adds his answer.
Edit again:
Maybe I'm forgetting something from C++, but the more I think about this, the more I wonder why you would ever write if (1 ^ 2) in the first place. The purpose for ^ is to exclusive-or two numbers together (which evaluates to another number), not convert them to boolean values and compare their truth values.
This seems like it would be an odd assumption for a language designer to make.
For non-bool operands, I guess what you would want is for a ^^ b to be evaluated as:
(a != 0) ^ (b != 0)
Well, you have the above option and you have a few options listed in other answers.
The operator ^^ would be redundant for bool operands. Talking only about boolean operands, for the sake of argument, let's pretend that ^ was bitwise-only and that ^^ existed as a logical XOR. You then have these choices:
& - Bitwise AND -- always evaluates both operands
&& - Logical AND -- does not always evaluate both operands
| - Bitwise OR -- always evaluates both operands
|| - Logical OR -- does not always evaluate both operands
^ - Bitwise XOR -- must always evaluate both operands
^^ - Logical XOR -- must always evaluate both operands
Why didn't they create ^^ to essentially convert numerical values into bools and then act as ^? That's a good question. Perhaps because it's more potentially confusing than && and ||, perhaps because you can easily construct the equivalent of ^^ with other operators.
I can't say what was in the heads of Kernighan and Ritchie when they invented C, but you made a brief reference to "wouldn't be short-circuiting", and I'm guessing that's the reason: It's not possible to implement it consistently. You can't short-circuit XOR like you can AND and OR, so ^^ could not fully parallel && and ||. So the authors might well have decided that making an operation that sort of kind of looks like its parallel to the others but isn't quite would be worse than not having it at all.
Personally, the main reason I use && and || is for the short-circuit rather than the non-bitwise. Actually I very rarely use the bitwise operators at all.
Another workaround to the ones posted above (even if it requires another branch in the code) would be:
if ( (a? !b : b ) )
that is equivalent to xor.
In Java the ^ operator indeed does do logical XOR when used on two boolean operands (just like & and | in Java do non-short-circuiting logical AND and OR, respectively, when applied to booleans). The main difference with C / C++ is that C / C++ allows you to mix integers and booleans, whereas Java doesn't.
But I think it's bad practice to use integers as booleans anyway. If you want to do logical operations, you should stick to either bool values, or integers that are either 0 or 1. Then ^ works fine as logical XOR.
An analogous question would be to ask, how would you do non-short-circuiting logical AND and OR in C / C++? The usual answer is to use the & and | operators respectively. But again, this depends on the values being bool or either 0 or 1. If you allow any integer values, then this does not work either.
Regardless of the case for or against ^^ as an operator, you example with strcmp() sucks. It does not return a truth value (true or false), it returns a relation between its inputs, encoded as an integer.
Sure, any integer can be interpreted as a truth value in C, in which case 0 is "false" and all other values are "true", but that is the opposite of what strcmp() returns.
Your example should begin:
int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"
You must compare the return value with 0 to convert it to a proper boolean value indicating if the strings were equal or not.
With "proper" booleans, represented canonically as 0 or 1, the bitwise ^ operator works a lot better, too ...
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.