What does (x ^ 0x1) != 0 mean?

21,814

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 is 1 in hex notation
  • x ^ 0x1 will invert the last bit of x (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... xoring x with 0x1 will result in 0 only if x is 0x1 ... this is an old trick mostly used in assembly language

Share:
21,814

Related videos on Youtube

KodeWarrior
Author by

KodeWarrior

Updated on July 08, 2022

Comments

  • KodeWarrior
    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
      raina77ow over 10 years
      Code obfuscation is quite standard.
    • Admin
      Admin over 10 years
      Few days ago I also got some similar situation stackoverflow.com/questions/19730348/why-101-is-11-in-c
    • Score_Under
      Score_Under over 10 years
      This 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
      Adriano Varoli Piazza over 10 years
      I don't see how if (1 != x) is hard to write.
    • chux - Reinstate Monica
      chux - Reinstate Monica over 10 years
      Various comments, first by @Spook, clearly point out that the type of x is not given - hence we do not know this is an integer in this C++ tagged problem. Sure, if this is C or x is an integer, the answer is easy, but that is not a given and the possibility of overloading operator ^ exists.
    • laike9m
      laike9m over 10 years
      I don't see how this gets so many upvotes...
  • Fred Foo
    Fred Foo over 10 years
    It's not x==0; 4 ^ 0x1 is true, but 4==0 is obviously false.
  • Andrew-Dufresne
    Andrew-Dufresne over 10 years
    "condition seems to be equal to if (x == 0)", doesn't it equal to x != 1?
  • Fiddling Bits
    Fiddling Bits over 10 years
    Typo in your answer. 10 != 1010
  • Spook
    Spook over 10 years
    Hey, 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
    Violet Giraffe over 10 years
    @Andrew-Dufresne: never mind, I made a mistake there. Edited it out.
  • Fiddling Bits
    Fiddling Bits over 10 years
    Is this faster than != 1?
  • David Heffernan
    David Heffernan over 10 years
    @Spook Not so. It's an equality test.
  • Paul R
    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
    Paul R over 10 years
    @BitFiddlingCodeMonkey: typo in your comment: 10 (decimal) == 1010 (binary)
  • Spook
    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
    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
    Ferenc Deak over 10 years
    in 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 to 0... however this question contains an xor 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
    theDmi over 10 years
    BUT the question is about C++, not C#
  • Igrek.
    Igrek. over 10 years
    @theDmi: BUT ALSO about bit manipulation and bitmask. Flag enum in C# is definitely about bitmask.
  • Igrek.
    Igrek. over 10 years
    Plus it can be useful in C++ as well. See : Stack 1 and Stack 2
  • Thom
    Thom over 10 years
    Unnecessarily 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
    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
    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
    TankorSmash over 10 years
    wouldn't 0b1010 be the Pythonic way of doing things?
  • mpdonadio
    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
    supercat over 10 years
    The equivalence presupposes that x is an integral type. If it's a float or double, then I believe the expression would yield true for 1.0 <= x < 2.0. And if x is a user-defined type, the expression could return true if x 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
    xryl669 over 10 years
    Actually 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
    bobobobo over 10 years
    @TheThom уєт уσυ ωяιтє ιи ¢ℓєαя тєχт
  • Synetech
    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
    Dave over 10 years
    This may not be identical to the test (x!=1), but it should be.
  • txtechhelp
    txtechhelp over 10 years
    Would this affect little/big endian systems differently?
  • Paul R
    Paul R over 10 years
    @txtechhelp: no, there is nothing endian-specific in the test.
  • fluffy
    fluffy over 10 years
    @supercat There is no operator^ for float/double.
  • supercat
    supercat over 10 years
    @fluffy: True, but I believe that in C values of float or double implicitly convert to int, do they not?
  • Ben Voigt
    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
    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
    Violet Giraffe over 10 years
    @txtechhelp: no, because 0x1 will be the same endianness.
  • Matt
    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
    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 new operator 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
    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 for q^1. Am I misremembering?
  • josefx
    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
    fluffy over 10 years
    @supercat Well, that depends on what type q is, obviously. You can certainly do a MyType::operator^(float) or similar.
  • Mysticial
    Mysticial over 10 years
    Is it really necessary to post yet another duplicate answer?
  • akbar ali
    akbar ali over 10 years
    you can say another answer but not duplicate. sorry if you mind
  • Leeor
    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
    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
    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
    Paul R about 7 years
    This answer doesn't seem to have anything to do with the original question, other than some discussion of the bitwise XOR operator ?