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

不想你离开。 提交于 2019-11-30 05:35:54

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.

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

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).

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).

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!