I’ve seen low-level bitwise expressions that use ~0
to generate a bit-pattern of all 1
s, which is then used as masks, etc. For example on K&R page 45:
/* getbits: get n bits from position p */
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p+1-n)) & ~(~0 << n);
}
In my machine, (unsigned long) ~0
evaluates to 0x FF FF FF FF FF FF FF FF
. This lets us easily generate 1
masks larger than int
s and is kinda nice.
However, shouldn’t (unsigned long) ~0
instead evaluate to 0x 00 00 00 00 FF FF FF FF
? Without any suffixes, 0
is considered an integer constant, so ~0
evaluates to 0x FF FF FF FF
. Why doesn’t casting this to unsigned long
result in a zero-padded value? What am I missing here?
Edit: On my machine, sizeof(int)
and sizeof(long)
are 4 and 8, respectively.
zero-padded value?
during integer promotion it pads with sign bit value (ie it is 1 padded for negative), otherwise(long)-1
will not be equal to-1L
– Elin~0
produces(int)0xffffffff = -1
Casting to an unsigned type produces the unique unsigned value which is equal to the original value modulo 2^n where n is the number of unsigned bits. In your case, n=64, and the unique 64-bit value which is equal to-1
modulo 2^64 is0xffffffffffffffff
. – Plumberysizeof(int) = 4
andsizeof(long)=8
. I also added this to the post. – Insincere(unsigned long)
of all 1's useULONG_MAX
or perhaps~0UL
or-1UL
. Avoid using signed constants for this task. – Tedderchar
s andshort
s without casting a~0u
to char? – Insincerechar
, usechar all_ones = CHAR_MAX | CHAR_MIN;
. Likewise forshort
. Yet be advised: avoid signed types for bit manipulation: stay withunsigned char
,unsigned short
,unsigned
, ... – Tedder