What does (x ^ 0x1) != 0 mean?
Solution 1
The XOR operation (x ^ 0x1
) inverts bit 0. So the expression effectively means: if bit 0 of x is 0, or any other bit of x is 1, then the expression is true.
Conversely the expression is false if x == 1.
So the test is the same as:
if (x != 1)
and is therefore (arguably) unnecessarily obfuscated.
Solution 2
-
^
is the bitwise XOR operation -
0x1
is1
in hex notation -
x ^ 0x1
will invert the last bit ofx
(refer to the XOR truth table in the link above if that's not clear to you).
So, the condition (0 != ( x ^ 0x1 ))
will be true if x
is greater than 1 or if the last bit of x
is 0. Which only leaves x==1 as a value at which the condition will be false. So it is equivalent to
if (x != 1)
P. S. Hell of a way to implement such a simple condition, I might add. Don't do that. And if you must write complicated code, leave a comment. I beg of you.
Solution 3
This may seem as oversimplified explanation, but if someone would like to go through it slowly it is below:
^
is a bitwise XOR operator in c, c++ and c#.
A bitwise XOR takes two bit patterns of equal length and performs the logical exclusive OR operation on each pair of corresponding bits.
Exclusive OR is a logical operation that outputs true whenever both inputs differ (one is true, the other is false).
The truth table of a xor b:
a b a xor b
----------------------------
1 1 0
1 0 1
0 1 1
0 0 0
So let's illustrate the 0 == ( x ^ 0x1 )
expression on binary level:
what? xxxxxxxx (8 bits)
xor 00000001 (hex 0x1 or 0x01, decimal 1)
gives 00000000
---------------------------
the only answer is 00000001
so:
0 == ( x ^ 0x1 ) => x == 1
0 != ( x ^ 0x1 ) => x != 1
Solution 4
It is exclusive OR (XOR) operator. To understand how it works you can run this simple code
std::cout << "0x0 ^ 0x0 = " << ( 0x0 ^ 0x0 ) << std::endl;
std::cout << "0x0 ^ 0x1 = " << ( 0x0 ^ 0x1 ) << std::endl;
std::cout << "0x1 ^ 0x0 = " << ( 0x1 ^ 0x0 ) << std::endl;
std::cout << "0x1 ^ 0x1 = " << ( 0x1 ^ 0x1 ) << std::endl;
The output will be
0x0 ^ 0x0 = 0
0x0 ^ 0x1 = 1
0x1 ^ 0x0 = 1
0x1 ^ 0x1 = 0
So this expression
0 != ( x ^ 0x1 )
will be equal true only when x != 0x1.
It does not change x itself. It only checks whether x is equal to 0 or 1. this rxpression could be changed to
if ( x != 0x1 )
Solution 5
It checks that x
is actually not 0x1
... xor
ing x
with 0x1
will result in 0 only if x
is 0x1
... this is an old trick mostly used in assembly language
Related videos on Youtube
KodeWarrior
Updated on July 08, 2022Comments
-
KodeWarrior almost 2 years
I came across the following code snippet
if( 0 != ( x ^ 0x1 ) ) encode( x, m );
What does
x ^ 0x1
mean? Is this some standard technique?-
raina77ow over 10 yearsCode obfuscation is quite standard.
-
Admin over 10 yearsFew days ago I also got some similar situation stackoverflow.com/questions/19730348/why-101-is-11-in-c
-
Score_Under over 10 yearsThis can be solved with the same approach as a "normal" equation:
0 != (x ^ 1)
→ xor both sides by 1 →(0 ^ 1) != (x ^ 1 ^ 1)
→ simplify →1 != x
-
Adriano Varoli Piazza over 10 yearsI don't see how
if (1 != x)
is hard to write. -
chux - Reinstate Monica over 10 yearsVarious comments, first by @Spook, clearly point out that the
type
ofx
is not given - hence we do not know this is an integer in this C++ tagged problem. Sure, if this is C orx
is an integer, the answer is easy, but that is not a given and the possibility of overloadingoperator ^
exists. -
laike9m over 10 yearsI don't see how this gets so many upvotes...
-
-
Fred Foo over 10 yearsIt's not
x==0
;4 ^ 0x1
is true, but4==0
is obviously false. -
Andrew-Dufresne over 10 years"condition seems to be equal to
if (x == 0)
", doesn't it equal tox != 1
? -
Fiddling Bits over 10 yearsTypo in your answer.
10 != 1010
-
Spook over 10 yearsHey, you don't know the context. If x is some kind of bit flag, it is IMO actually more clear to write it as it is now than using the != operator.
-
Violet Giraffe over 10 years@Andrew-Dufresne: never mind, I made a mistake there. Edited it out.
-
Fiddling Bits over 10 yearsIs this faster than
!= 1
? -
David Heffernan over 10 years@Spook Not so. It's an equality test.
-
Paul R over 10 years@Spook: it's not just testing a single bit flag though - it's testing the entire width of x. If you just want to test a single bit then there are clearer idioms, such as using a bitwise AND.
-
Paul R over 10 years@BitFiddlingCodeMonkey: typo in your comment:
10 (decimal) == 1010 (binary)
-
Spook over 10 years@larsmans I don't want to check if only one flag is set. I want to check if 0th flag is not set and any other is.
-
Fiddling Bits over 10 years@PaulR How is anybody supposed to know what's decimal and what's binary if you don't put a
b
or something there? -
Ferenc Deak over 10 yearsin ancient times while doing manual assembly optimizations (x86) if I remember correctly the
xor
approach contained less machine code and was executed faster than the corresponding assignment to0
... however this question contains anxor
AND a comparison, so I might think that the!=
might be faster. I'm not so sure however, would need to see some compiler generated assembly. -
theDmi over 10 yearsBUT the question is about C++, not C#
-
Igrek. over 10 years@theDmi: BUT ALSO about bit manipulation and bitmask. Flag enum in C# is definitely about bitmask.
-
Igrek. over 10 years
-
Thom over 10 yearsUnnecessarily obfuscated? Don't you know that it's our job to obfuscate code. If we wrote simple code that anyone could understand, why, where would go the religious sanctity of our positions in the world? We'd suddenly be common workers like everyone else. Obfuscation is inherently necessary.
-
Matt over 10 years@BitFiddlingCodeMonkey: No. If XOR was faster than some native level equality test, your compiler would emit XORs to test for equality. Hence, XORs are never faster than equality tests on optimizing compilers. Rule 101 of writing fast code is "don't try and help the compiler. You'll only end up making unreadable code that's slower in practice".
-
Matt over 10 years@Spook: Even then, testing the entire chain for equality is more readable and immediately understandable than doing an XOR, so it's bad practice to use an XOR when an == will do.
-
TankorSmash over 10 yearswouldn't 0b1010 be the Pythonic way of doing things?
-
mpdonadio over 10 years@fritzone IIRC, the XOR tricks had more to do with saving registers, saving a register load b/c the literal could be encoded directly in the OP in some cases, and some subtle differences with status flags (but most of my assembly was on 68k and DSP).
-
supercat over 10 yearsThe equivalence presupposes that
x
is an integral type. If it's afloat
ordouble
, then I believe the expression would yield true for1.0 <= x < 2.0
. And ifx
is a user-defined type, the expression could return true ifx
is a Yugo, kangaroo, famous composer's birthday, or any number which shares at least three digits with the current dollar-denominated price of tea in China. -
xryl669 over 10 yearsActually Spook is right. The test (x != 1) is not equivalent. The code can be C++ (and in C++, ^ can be an operator that does anything). So you don't know the context, @Spook is right.
-
bobobobo over 10 years@TheThom уєт уσυ ωяιтє ιи ¢ℓєαя тєχт
-
Synetech over 10 years@TheThom, you must be living under a rock. Programmers have long since become obsolete; ever since the Internet took off and personal computers became ubiquitous. These days, everybody and their dog are “programmers” thanks to 4GLs (and misnomered 5GLs).
-
Dave over 10 yearsThis may not be identical to the test (x!=1), but it should be.
-
txtechhelp over 10 yearsWould this affect little/big endian systems differently?
-
Paul R over 10 years@txtechhelp: no, there is nothing endian-specific in the test.
-
fluffy over 10 years@supercat There is no
operator^
forfloat
/double
. -
supercat over 10 years@fluffy: True, but I believe that in C values of
float
ordouble
implicitly convert toint
, do they not? -
Ben Voigt over 10 years@supercat: When a conversion from floating-point to integer is called for, the conversion is implicit (doesn't require cast syntax). But no conversion is triggered by bitwise operators, they simply fail for floating-point types.
-
supercat over 10 years@BenVoigt: Okay, thanks. It would still be possible for user-defined types to overload
^
(and for that matter==
) in various interesting fashions. -
Violet Giraffe over 10 years@txtechhelp: no, because 0x1 will be the same endianness.
-
Matt over 10 years@MPD: Normally it's to do with clearing a register (at least on 386+). xor eax, eax sets eax to zero in two bytes, but mov eax, 0 takes three or six bytes (depending on the encoding), and takes slightly longer to decode than the xor form.
-
fluffy over 10 years@supercat You can't define new
operator
functions for fundamental types, for two reasons: 1) it's not a function, and 2) you can't just create a newoperator
for any type that conflicts with an existing definition anyway, because otherwise you run into all sorts of crazy with "which one do you mean?" at link time. -
supercat over 10 years@fluffy: I thought C++ operator types were bound to the left operand, so one couldn't define a new meaning for
1^q
, but could forq^1
. Am I misremembering? -
josefx over 10 years@xryl669 then the code should be removed along with the responsible developer. Miss use of operators makes code hard to read and maintain . Either the operator^ behaves like developers expect it to (XOR) or it leads to unexpected behavior as you can see from the responses/comments (every one assumes it is XOR).
-
fluffy over 10 years@supercat Well, that depends on what type
q
is, obviously. You can certainly do aMyType::operator^(float)
or similar. -
Mysticial over 10 yearsIs it really necessary to post yet another duplicate answer?
-
akbar ali over 10 yearsyou can say another answer but not duplicate. sorry if you mind
-
Leeor about 10 years@PaulR, may be worth mentioning that the XOR operation inverts all the bits that are on in the other argument, which happens in this case to be bit 0 only. It could be a little misleading if read out of context
-
user207421 about 9 years@Leeor No it doesn't. It inverts all the bits that are on in both arguments, or off in both arguments, and leaves the bits arhat are on in one and not the other.
-
Leeor about 9 years@EJP, you're wrong. bits that are off in both argument will be off in the result, how is that an inversion? Anyway, when one argument is a mask, it's more natural to look at the impact on the other argument, which is exactly to toggle (a.k.a invert) the bits that are on in the mask.
-
Paul R about 7 yearsThis answer doesn't seem to have anything to do with the original question, other than some discussion of the bitwise XOR operator ?