问题
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
?
回答1:
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:
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
回答3:
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).
回答4:
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).
回答5:
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.
回答6:
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
来源:https://stackoverflow.com/questions/46376693/what-is-the-purpose-of-int-mask-0