Unknown system bitsize for int, how to create mask

Viewed 57

I would like to create a mask for the MSB only, however the width of the int on the operating system is suppose to be unknown, so you cannot assume 32 bits.

see the following

    // THE FOLLOWING FAILS BECAUSE OF SYSTEM IMPLEMENTING A LOGICAL 
    // RIGHT SHIFT
    // Idea is 
    //     1. 0 inverted = all 1's
    //     2. Arithmetic shift right
    //     3. Then invert again to preseve MSB '1'
    const int unsigned mask = ~(~0>>1); // FAIL, because of logic shift

Assuming 16 bit system

  1. ~0 give FFFF
  2. ~0>>1 give 7FFF
  3. ~(~0 >> 1) give 8000
3 Answers

You should add an u suffix to make what is shifted unsigned so that logical right shift is performed instead of arithmetic one.

const int unsigned mask = ~(~0u>>1);

You can just left shift the (unsigned) value 1 by the number of bits in the type minus 1 (i.e. for a 32-bit type, the MSB will be 1 << 31). To get the number of bits, use a combination of the sizeof operator and the CHAR_BIT constant (defined in <limits.h>):

const unsigned int MSB = 1u << (sizeof(unsigned int) * CHAR_BIT - 1);

INT_MAX is the int bit pattern of 0111...1111 (of some width)* for all implementations.

To form 1000...0000, invert those bits.

~INT_MAX

The above treads on undefined beahvior (UB).
Better to looks to unsigned or wider types.

unsigned mask = ~(unsigned) INT_MAX;

On rare machines, INT_MAX == UINT_MAX, so on those, look to wider types:

long long = ~(long long) INT_MAX;

On rarer machines (unheard of), INT_MAX == LONG_MAX is also true, then we are out of luck.


Pedantic: Rare machines use padding on int/unsigned, so best to drive code with (U)INT_MAX than sizeof.


* Maybe some padding bits too - very rare.

Related