# # Bit Operators

## # | - bitwise OR

```
int a = 5; // 0101b (0x05)
int b = 12; // 1100b (0x0C)
int c = a | b; // 1101b (0x0D)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
```

**Output**

`a = 5, b = 12, c = 13`

**Why**

A bit wise `OR`

operates on the bit level and uses the following Boolean truth table:

```
true OR true = true
true OR false = true
false OR false = false
```

When the binary value for `a`

(`0101`

) and the binary value for `b`

(`1100`

) are `OR`

'ed together we get the binary value of `1101`

:

```
int a = 0 1 0 1
int b = 1 1 0 0 |
---------
int c = 1 1 0 1
```

The bit wise OR does not change the value of the original values unless specifically assigned to using the bit wise assignment compound operator `|=`

:

```
int a = 5; // 0101b (0x05)
a |= 12; // a = 0101b | 1101b
```

## # ^ - bitwise XOR (exclusive OR)

```
int a = 5; // 0101b (0x05)
int b = 9; // 1001b (0x09)
int c = a ^ b; // 1100b (0x0C)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
```

**Output**

`a = 5, b = 9, c = 12`

**Why**

A bit wise `XOR`

(exclusive or) operates on the bit level and uses the following Boolean truth table:

```
true OR true = false
true OR false = true
false OR false = false
```

Notice that with an XOR operation `true OR true = false`

where as with operations `true AND/OR true = true`

, hence the exclusive nature of the XOR operation.

Using this, when the binary value for `a`

(`0101`

) and the binary value for `b`

(`1001`

) are `XOR`

'ed together we get the binary value of `1100`

:

```
int a = 0 1 0 1
int b = 1 0 0 1 ^
---------
int c = 1 1 0 0
```

The bit wise XOR does not change the value of the original values unless specifically assigned to using the bit wise assignment compound operator `^=`

:

```
int a = 5; // 0101b (0x05)
a ^= 9; // a = 0101b ^ 1001b
```

The bit wise XOR can be utilized in many ways and is often utilized in bit mask operations for encryption and compression.

**Note:** The following example is often shown as an example of a nice trick. But should not be used in production code (there are better ways `std::swap()`

to achieve the same result).

You can also utilize an XOR operation to swap two variables without a temporary:

```
int a = 42;
int b = 64;
// XOR swap
a ^= b;
b ^= a;
a ^= b;
std::cout << "a = " << a << ", b = " << b << "\n";
```

To productionalize this you need to add a check to make sure it can be used.

```
void doXORSwap(int& a, int& b)
{
// Need to add a check to make sure you are not swapping the same
// variable with itself. Otherwise it will zero the value.
if (&a != &b)
{
// XOR swap
a ^= b;
b ^= a;
a ^= b;
}
}
```

So though it looks like a nice trick in isolation it is not useful in real code. xor is not a base logical operation,but a combination of others: a^c=~(a&c)&(a|c)

also in 2015+ compilers variables may be assigned as binary:

```
int cn=0b0111;
```

## # & - bitwise AND

```
int a = 6; // 0110b (0x06)
int b = 10; // 1010b (0x0A)
int c = a & b; // 0010b (0x02)
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
```

**Output**

`a = 6, b = 10, c = 2`

**Why**

A bit wise `AND`

operates on the bit level and uses the following Boolean truth table:

```
TRUE AND TRUE = TRUE
TRUE AND FALSE = FALSE
FALSE AND FALSE = FALSE
```

When the binary value for `a`

(`0110`

) and the binary value for `b`

(`1010`

) are `AND`

'ed together we get the binary value of `0010`

:

```
int a = 0 1 1 0
int b = 1 0 1 0 &
---------
int c = 0 0 1 0
```

The bit wise AND does not change the value of the original values unless specifically assigned to using the bit wise assignment compound operator `&=`

:

```
int a = 5; // 0101b (0x05)
a &= 10; // a = 0101b & 1010b
```

## # << - left shift

```
int a = 1; // 0001b
int b = a << 1; // 0010b
std::cout << "a = " << a << ", b = " << b << std::endl;
```

**Output**

`a = 1, b = 2`

**Why**

The left bit wise shift will shift the bits of the left hand value (`a`

) the number specified on the right (`1`

), essentially padding the least significant bits with 0's, so shifting the value of `5`

(binary `0000 0101`

) to the left 4 times (e.g. `5 << 4`

) will yield the value of `80`

(binary `0101 0000`

). You might note that shifting a value to the left 1 time is also the same as multiplying the value by 2, example:

```
int a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a <<= 1;
}
a = 7;
while (a < 200) {
std::cout << "a = " << a << std::endl;
a *= 2;
}
```

But it should be noted that the left shift operation will shift *all* bits to the left, including the sign bit, example:

```
int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1; // 1111 1111 1111 1111 1111 1111 1111 1110
std::cout << "a = " << a << ", b = " << b << std::endl;
```

Possible output: `a = 2147483647, b = -2`

While some compilers will yield results that seem expected, it should be noted that if you left shift a signed number so that the sign bit is affected, the result is **undefined**. It is also **undefined** if the number of bits you wish to shift by is a negative number or is larger than the number of bits the type on the left can hold, example:

```
int a = 1;
int b = a << -1; // undefined behavior
char c = a << 20; // undefined behavior
```

The bit wise left shift does not change the value of the original values unless specifically assigned to using the bit wise assignment compound operator `<<=`

:

```
int a = 5; // 0101b
a <<= 1; // a = a << 1;
```

## # >> - right shift

```
int a = 2; // 0010b
int b = a >> 1; // 0001b
std::cout << "a = " << a << ", b = " << b << std::endl;
```

**Output**

`a = 2, b = 1`

**Why**

The right bit wise shift will shift the bits of the left hand value (`a`

) the number specified on the right (`1`

); it should be noted that while the operation of a right shift is standard, what happens to the bits of a right shift on a *signed negative* number is *implementation defined* and thus cannot be guaranteed to be portable, example:

```
int a = -2;
int b = a >> 1; // the value of b will be depend on the compiler
```

It is also undefined if the number of bits you wish to shift by is a negative number, example:

```
int a = 1;
int b = a >> -1; // undefined behavior
```

The bit wise right shift does not change the value of the original values unless specifically assigned to using the bit wise assignment compound operator `>>=`

:

```
int a = 2; // 0010b
a >>= 1; // a = a >> 1;
```

## # ~ - bitwise NOT (unary complement)

```
unsigned char a = 234; // 1110 1010b (0xEA)
unsigned char b = ~a; // 0001 0101b (0x15)
std::cout << "a = " << static_cast<int>(a) <<
", b = " << static_cast<int>(b) << std::endl;
```

**Output**

`a = 234, b = 21`

**Why**

A bit wise `NOT`

(unary complement) operates on the bit level and simply flips each bit. If it's a `1`

, it's changed to a `0`

, if it's a `0`

, it's changed to a `1`

. The bit wise NOT has the same effect as XOR'ing a value against the max value for a specific type:

```
unsigned char a = 234; // 1110 1010b (0xEA)
unsigned char b = ~a; // 0001 0101b (0x15)
unsigned char c = a ^ ~0;
```

The bit wise NOT can also be a convenient way to check the maximum value for a specific integral type:

```
unsigned int i = ~0;
unsigned char c = ~0;
std::cout << "max uint = " << i << std::endl <<
"max uchar = " << static_cast<short>(c) << std::endl;
```

The bit wise NOT does not change the value of the original value and does not have a compound assignment operator, so you can not do `a ~= 10`

for example.

The *bit wise* NOT (`~`

) should not be confused with the *logical* NOT (`!`

); where a bit wise NOT will flip each bit, a logical NOT will use the whole value to do its operation on, in other words `(!1) != (~1)`

#### # Remarks

Bit shift operations are not portable across all processor architectures, different processors can have different bit-widths. In other words, if you wrote

```
int a = ~0;
int b = a << 1;
```

This value would be different on a 64 bit machine vs. on a 32 bit machine, or from an x86 based processor to a PIC based processor.

Endian-ness does not need to be taken into account for the bit wise operations themselves, that is, the right shift (`>>`

) will shift the bits towards the least significant bit and an XOR will perform an exclusive or on the bits. Endian-ness only needs to be taken into account with the data itself, that is, if endian-ness is a concern for your application, it's a concern regardless of bit wise operations.