views:

765

answers:

6

Is there such a thing? First time I encountered a practical need for it, but I don't see one listed in stroustrup. I intend to write:

// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);

But there is no ^^ operator. Can I use bitwise ^ here and get the right answer (regardless of machine representation of true and false)? I never mix & and &&, or | and ||, so I hesitate to do that with ^ and ^^.

I'd be more comfortable writing my own "bool XOR(bool,bool)" function instead.

+12  A: 

The XOR operator cannot be short circuited; i.e. you cannot predict the result of an XOR expression just by evaluating its left hand operand. Thus, there's no reason to provide a ^^ version.

Mehrdad Afshari
Just to clarify, that means to check for XOR you have to evaluate both parts of the test. So there is no advantage to having a symbol. C/C++ is allowed to skip unecessary parts of a comparison if the over result is known after the first test.
Martin Beckett
RAC
Mehrdad Afshari
Brian Postow
Johannes Schaub - litb
Brian Postow
AndreyT
AndreyT
Brian Postow
@Brain, yes the reason that the answer doesn't handle converting to `true` or `false` from non-zero and zero is that `!=` already does this, i think (only mehrdad can know for sure, of course). So the only property `^^` would have left is short curciut (which `!=` doesn't have). But as this answer also points out, this is nonsensical for `^^`
Johannes Schaub - litb
Brian Postow
litb: Converting to true and false isn't really the issue. The issue is that logical operators behave differently than bitwise operators when given values that are neither 1 nor 0.
Brian Postow
AndreyT
Brian Postow
@Brian the point is that if you give `^^` a "logical" mood without short-circuit, then `^^` is not any different to `!=`. This answer hilights a difference to `!=` that `^^` would have, but which would not make sense.
Johannes Schaub - litb
Also C++ != other-languages. In C and C++ as shown above short circuit is not just some-nice-to-have-stuff but it's fundamentally important. :)
Johannes Schaub - litb
litb: That's true. However, I think that the important part of that explanation is that you can use !=, not that it doesn't allow short circuiting.
Brian Postow
litb: It's actually NOT fundamentally important. You can always split it into multiple if... it's just a convenience like ++. Fundamentally, though I think we're getting into a discussion of language design here. I think we all understand and agree on what is "true". We disagree on what is "important" and that skirts into opinion territory. B-)
Brian Postow
Mehrdad Afshari
Also, the more I think about this, the more I think that C *SHOULD* have a ^^ operator, that would avoid having to negate both sides (or some other normalization to 1/0) before doing !=... I'm guessing it's not because xor isn't used nearly as often... but your mileage may vary...
Brian Postow
Brian Postow
Then you should read Dennis Ritchie's answer to why it doesn't exist: http://www.it.usyd.edu.au/~dasymond/mirror/c-faq/misc/xor.dmr.html
Johannes Schaub - litb
@Brian: My comment applies to typed languages in general and AFAIK, both C and C++ in their current versions have `bool` types. The difference is that C, C++ support coercions from ints to bools.
Mehrdad Afshari
@mehrdad that does appear to be the case for C++, but not C...
Brian Postow
@Brian: C99 is 10 years old now. It does have a `bool` type.
Mehrdad Afshari
Mehrdad: On my computer, in gcc 4.2 bool does not compile. g++ it does.
Brian Postow
@Brian Postow: I don't know where you get that strange info about `bool` type. C89/90 didn't have a real boolean type, but `bool` in C++ and `Bool_` in C99 are true dedicated boolean types.
AndreyT
@litb: I stand corrected. If Dennis Ritchie says it, it must be true. I still think it would be a useful short-cut like ++, but I bow to the experience of Ritchie.
Brian Postow
@Brian Postow: In C99 the type is called `Bool_`. And there's a macro `bool` defined in `stdbool.h`.
AndreyT
@AndreyT: Brians-mini$ gcc-4.2 foo.cfoo.c: In function 'main':foo.c:5: error: 'Bool_' undeclared (first use in this function)... foo.c:6: error: 'bool' undeclared (first use in this function)
Brian Postow
@Brian Postow: The key moment being that it exists in C99 only. You need to compile with `-std=c99` switch. to make gcc work in C99 mode. It is nor default still.
AndreyT
@AndreyT: It's '_Bool' not 'Bool_'. It's surprising to me that C and C++ would have different names... odd.
Brian Postow
Sorry, its `_Bool`, not `Bool_`.
AndreyT
+35  A: 

The != operator serves this purpose for bool values.

Greg Hewgill
Haha, good point! Will use that.
RAC
If both are false, doesn't the XOR should return false??? In this case, the != would return true.
David Brunelle
David: F != F ==> F.
Brian Postow
@David Brunelle: Huh? What makes you think that `false != false` would evaluate to `true`?
AndreyT
But false != false => false
Jonas
Note that this only works for booleans. And ^ would work perfectly well there. 2 !=1 => 1 which is not what you want! as LiraNuna says, putting a ! infront of both sides solves that problem. but again, then you can use bitwise ^...
Brian Postow
Right, I was careful to mention "for `bool` values" because it doesn't necessarily do what you might want for non-booleans. And as this is C++, there exists a real `bool` type instead of having to use `int` for that purpose.
Greg Hewgill
If you want to do it for type `a` just write `!(a) != !(a)`
Chris Lutz
+7  A: 

Proper manual logical XOR implementation depends on how closely you want to mimic the general behavior of other logical operators (|| and &&) with your XOR. There are two important things about these operators: A) they guarantee short-circuit evaluation, B) they introduce a sequence point.

XOR evaluation, as you understand, cannot be short-circuited. So A is out of question. But what about B? If you don't care about B, then with normalized (i.e. bool) values operator != does the job of XOR in terms of the result. And the operands can be easily normalized with unary !, if necessary.

If you care about the extra sequence point though, neither != nor bitwise ^ is the proper way to implement XOR. One possible way to do XOR(a, b) correctly might look as follows

a ? !b : b

This is actually as close as you can get to making a homemade XOR "similar" to || and &&. This will only work, of course, if you implement your XOR as a macro. A function won't do, since the sequencing will not apply to function's arguments.

Someone might say though, that the only reason of having a sequence point at each && and || is to support the short-circuited evaluation, and thus XOR does not need one. This makes sense, actually. Yet, it is worth considering having a XOR with a sequence point in the middle.

For example, the following expression

++x > 1 && x < 5

has defined behavior and specificed result in C/C++ (with regard to sequencing at least). So, one might reasonably expect the same from user-defined logical XOR, as in

XOR(++x > 1, x < 5)

while a !=-based XOR doesn't have this property.

AndreyT
A: 

I use "xor" (it seems its a keyword, in codeblocks at least it gets bold) just as you can use "and" instead of && and "or" instead of ||.

if(first xor second)...

Edit. Yes it is bitwise sorry.

csiz
I'm guessing that those are hidden #defines from somewhere. I'm pretty sure "and" and "xor" aren't keywords in ansi C... ( at least not C79)
Brian Postow
`xor` is identical to `^` ...
Johannes Schaub - litb
@Brian Postow: I don't know what C79 is, but in C++98 `and` and `xor` are standard library macros. Thay are not from "somewhere", they are from <iso646.h>. These macros are also in C99 (not sure about C89/90).
AndreyT
@Brian Postow: ... `xor` stands for *bitwise* xor though, while `and` is *logical* and.
AndreyT
Brian Postow
and Andrey, you are correct. xor does not do logical xor, as 1 xor 2 => 3 which is true, and you want it to be false...
Brian Postow
@Andrey - I've never seen anything about these macros in C99. They're easy to implement, and I bet many implementations will provide them, but please cite where the standard mandates them.
Chris Lutz
They are certainly in C99 using that header. In C++, they are integrated into the language as "alternative tokens", and you can do `struct A { compl A() { } };` to define a destructor, for example.
Johannes Schaub - litb
i believe it's not part of C89, but it's part of the normative addendum that was released as C94: http://www.lysator.liu.se/c/na1.html .
Johannes Schaub - litb
+6  A: 

For a true logical XOR operation, this will work:

if(!A != !B) {
    // code here
}
LiraNuna
Excellent point. You need the ! to normalize to booleans!
Brian Postow
This is too cool. :)
Daniel Trebbien
A: 

If your not using C++, you can define xor like this:

#define xor != 0 ^ !!

The you can use it like this:

if (a xor b)

AFAICT there isn't any problem with it.

Joe D