I have a masking procedure (which creates an all-ones bit mask for the bottom half for a given size):
template<class T>
T bottom_half() {
T halfway = ((sizeof(T) * 8) / 2);
T mask = (1 << halfway) - 1;
return mask;
}
which works fine if I call bottom_half<int>()
or long
or char
. But for some reason when I run it with long long
, halfway
is correctly set to 32
, but mask
is 0
. Why would that be?
Bit masks are used to access specific bits in a byte of data. This is often useful as a method of iteration, for example when sending a byte of data serially out a single pin. In this example the pin needs to change its state from high to low for each bit in the byte to be transmitted.
Masking is the act of applying a mask to a value. This is accomplished by doing: Bitwise ANDing in order to extract a subset of the bits in the value. Bitwise ORing in order to set a subset of the bits in the value. Bitwise XORing in order to toggle a subset of the bits in the value.
Bitmask also known as mask is a sequence of N -bits that encode the subset of our collection. The element of the mask can be either set or not set (i.e. 0 or 1). This denotes the availability of the chosen element in the bitmask. For example, an element i is available in the subset if the ith bit of mask is set.
The left shift is shifting 1, which is int
by default and probably 32 bits on your machine. When you shift 1<<32
, the result is undefined, which means it is not predictable anymore, as it could be anything.
On some processors, 1<<32
might result in shifting the bit off the high end of the integer and resulting in 0. On other processors, the 32 shift is modulo the register size, so effective it is a zero shift, and the result is 1. In any case, it is undefined.
(See What's bad about shifting a 32-bit variable 32 bits? for a discussion on this).
Note also that sizeof
returns units char
or "bytes" (these are defined to be the same in C, sizeof(char) == 1
always), but C does not guarantee that a byte is 8 bits. There is standard macro CHAR_BIT
to get the bit size of a char
.
Try this
#include <limits.h>
template<class T>
T bottom_half() {
T halfway = ((sizeof(T) * CHAR_BIT) / 2);
T mask = ((T)1 << halfway) - 1;
return mask;
}
The expression 1 << x
has type int
. Left-shifting a signed type such that the value exceeds the maximum representable value has undefined behavior. Use T(1) << x
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With