What is the purpose of "int mask = ~0;"?

6.3k views Asked by At

I saw the following line of code here in C.

 int mask = ~0;

I have printed the value of mask in C and C++. It always prints -1.

So I do have some questions:

  • Why assigning value ~0 to the mask variable?
  • What is the purpose of ~0?
  • Can we use -1 instead of ~0?
6

There are 6 answers

16
Richard Hodges On BEST ANSWER

It's a portable way to set all the binary bits in an integer to 1 bits without having to know how many bits are in the integer on the current architecture.

2
phuclv On

C and C++ allow 3 different signed integer formats: sign-magnitude, one's complement and two's complement

~0 will produce all-one bits regardless of the sign format the system uses. So it's more portable than -1

You can add the U suffix (i.e. -1U) to generate an all-one bit pattern portably1. However ~0 indicates the intention clearer: invert all the bits in the value 0 whereas -1 will show that a value of minus one is needed, not its binary representation

1 because unsigned operations are always reduced modulo the number that is one greater than the largest value that can be represented by the resulting type

0
6502 On

That on a 2's complement platform (that is assumed) gives you -1, but writing -1 directly is forbidden by the rules (only integers 0..255, unary !, ~ and binary &, ^, |, +, << and >> are allowed).

1
bartop On

There are multiple ways of encoding numbers across all computer architectures. When using 2's complement this will always be true:~0 == -1. On the other hand, some computers use 1's complement for encoding negative numbers for which the above example is untrue, because ~0 == -0. Yup, 1s complement has negative zero, and that is why it is not very intuitive.

So to your questions

  • the ~0 is assigned to mask so all the bits in mask are equal 1 -> making mask & sth == sth
  • the ~0 is used to make all bits equal to 1 regardless of the platform used
  • you can use -1 instead of ~0 if you are sure that your computer platform uses 2's complement number encoding

My personal thought - make your code as much platform-independent as you can. The cost is relatively small and the code becomes fail proof

6
skaak On

Loooong ago this was how you saved memory on extremely limited equipment such as the 1K ZX 80 or ZX 81 computer. In BASIC, you would

Let X = NOT PI

rather than

LET X = 0

Since numbers were stored as 4 byte floating points, the latter takes 2 bytes more than the first NOT PI alternative, where each of NOT and PI takes up a single byte.

0
chqrlie On

You are studying a coding challenge with a number of restrictions on operators and language constructions to perform given tasks.

The first problem is return the value -1 without the use of the - operator.

On machines that represent negative numbers with two's complement, the value -1 is represented with all bits set to 1, so ~0 evaluates to -1:

/* 
 * minusOne - return a value of -1 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int minusOne(void) {
  // ~0 = 111...111 = -1
  return ~0;
}

Other problems in the file are not always implemented correctly. The second problem, returning a boolean value representing the fact the an int value would fit in a 16 bit signed short has a flaw:

/* 
 * fitsShort - return 1 if x can be represented as a 
 *   16-bit, two's complement integer.
 *   Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 1
 */
int fitsShort(int x) {
  /* 
   * after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
   * so after shift, if x remains the same, then it means that x can be represent as 16-bit
  */
  return !(((x << 16) >> 16) ^ x); 
}

Left shifting a negative value or a number whose shifted value is beyond the range of int has undefined behavior, right shifting a negative value is implementation defined, so the above solution is incorrect (although it is probably the expected solution).