Reputation: 33
How do I set the first (least significant) eight bits of any integer type to all zeroes? Essentially do a bitwise AND of any integer type with 0x00
.
What I need is a generic solution that works on any integer size, but not have to create a mask setting all the higher bits to 1
.
In other words:
0xffff & 0x00 = 0xff00
0xaabbccddeeffffff & 0x00 = 0xaabbccddeeffff00
Upvotes: 2
Views: 1189
Reputation: 140970
With bit shifts:
any_unsigned_integer = any_unsigned_integer >> 8 << 8;
Upvotes: 4
Reputation: 144695
The simplest solution works for all integer types on architectures with 2's complement representation for negative numbers:
val = val & ~0xff;
The reason is ~0xff
evaluates to -256
with type int
. Let's consider all possible types for val
:
val
is smaller than int
, val
is promoted to int
, the mask operation works as expected and the result is converted back to the type of val
.val
is signed, -256
is converted to type of val
preserving its value, hence replicating the sign bit, and the mask is performed properly.val
is unsigned, converting -256
to this type produces the value TYPE_MAX + 1 - 256
that has all bits set except the 8 low bits, again the proper mask for the operation.Another simple solution, that works for all representations of negative values is this:
val = val ^ (val & 0xff);
It requires storing the value into a variable to avoid multiple evaluation, whereas the first proposal can be applied to any expression with potential side-effects:
return my_function(a, b, c) & ~0xff;
Upvotes: 3
Reputation: 67476
Universal solution no mask, any number of bits
#define RESETB(val, nbits) ((val) ^ ((val) & ((1ULL << (nbits)) - 1)))
or even better
#define RESETB(val, nbits) ((val) ^ ((val) & ((nbits) ? ((nbits) >= sizeof(val) * CHAR_BIT ? ((1ULL << (sizeof(val) * CHAR_BIT)) - 1) : ((1ULL << (nbits)) - 1)) : 0)))
Upvotes: 0
Reputation: 881323
The C not operator ~
will invert all the bits of a given value so, in order to get a mask that will clear only the lower eight bits:
int val = 123456789;
int other_val = val & ~0xff; // AND with binary 1111 ... 1111 0000 0000
val &= ~0xff; // alternative to change original variable.
If you have a wider (or thinner) type, the 0xff
should be of the correct type, for example:
long val = 123456789L;
long other_val = val & ~(long)0xff;
val &= ~(long)0xff; // alternative to change original variable.
Upvotes: 2
Reputation: 17403
One way to do it without a creating a mask for the higher bits is to use a combination of the &
and ^
operators: x = x ^ (x & 0xFF);
(or, using compound assignment: x ^= x & 0xFF;
).
Upvotes: 1