When you see such masks - remember these key rules for bitwise arithmetic
Assume X is unknown, & is bitwise AND, | is bitwise OR
- X & 1 = X
- X & 0 = 0
- X | 0 = X
- X | 1 = 1
Now look at the mask and its operation. In this case
v7 | 0x8000000000000000LL
The mask
In [1]: 0x8000000000000000 == 1 << 63
Out[1]: True
So in this case a 64 bit number - with the most significant bit (MSB) set and all other 0s
index - 63 62 61 ... 2 1 0
bits - 1 0 0 ... 0 0 0
The operation here is |
- the bitwise OR
We don't know v7
- we can assume it to be X. For individual bits X_i
for i
index
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
When bitwise OR is done -
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
mask - 1 0 0 ... 0 0 0
With the rules mentioned above - we can operate X | 1 = 1
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
mask - 1 0 0 ... 0 0 0
result- 1
for the rest unknown bits X | 0 = X
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
mask - 1 0 0 ... 0 0 0
result- 1 X_62 X_61 ... X_2 X_1 X_0
We can see that all of the bits of result
is the same as v7
except the MSB which is now 1.
Therefore, v7 | 0x8000000000000000LL
sets the MSB of v7
Similarly for v7 & 0x7FFFFFFFFFFFFFFFLL
The mask is 0x7FFFFFFFFFFFFFFFLL, which has all bits set to 1 except for the most significant bit (MSB), which is 0.
index - 63 62 61 ... 2 1 0
bits - 0 1 1 ... 1 1 1
We want to perform the bitwise AND operation between v7
and the mask.
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
When we perform the bitwise AND operation:
For each bit position, we apply the rule X & 1 = X
and X & 0 = 0
index - 63 62 61 ... 2 1 0
bitsX - X_63 X_62 X_61 ... X_2 X_1 X_0
mask - 0 1 1 ... 1 1 1
result- 0 X_62 X_61 ... X_2 X_1 X_0
The result retains all bits of v7
except the MSB, which is now 0. Therefore, v7 & 0x7FFFFFFFFFFFFFFFLL
clears the MSB of v7
In signed values the MSB dictates the sign of the number - a set MSB means -ve and unset means a +ve number.
Now if v7
is a signed value - we can see the change in values with this python snippet
In [9]: x = 0xabcdef1234567890
In [10]: ctypes.c_uint64(x & 0x7FFFFFFFFFFFFFFF)
Out[10]: c_ulong(3156441775323117712)
In [11]: (ctypes.c_int64(x & 0x7FFFFFFFFFFFFFFF).value)
Out[11]: 3156441775323117712
In [12]: ctypes.c_int64(x).value
Out[12]: -6066930261531658096
With the MSB cleared the signed and unsigned values of the result is same.
In [13]: (ctypes.c_int64(x | 0x8000000000000000).value)
Out[13]: -6066930261531658096
In [14]: (ctypes.c_uint64(x | 0x8000000000000000).value)
Out[14]: 12379813812177893520
In [15]: x
Out[15]: 12379813812177893520
With the MSB set - the number stays as is if it was a signed negative earlier.
"normal" C coding pattern
?C bitwise operators