Using the bitwise complement operator (unary ~ ) for a signed integer has implementation-specific and undefined aspects . In other words, this code is not portable, even if you are considering only two implementations of the add-on.
It is important to note that even two complement representations in C can have trap representations. 6.2.6.2p2 even clearly states this :
If the sign bit is one, the value must be changed in one of the following ways:
- the corresponding value with the sign bit 0 is negated (sign and value);
- the sign bit has a value of - (2 M) (two additions);
- the sign bit has the meaning - (2 M - 1) (addition to them).
Which of them relates to the implementation, as well as the value with the sign bit 1 and all bits of the values 0 (for the first two) or with the familiar bit and all bits of the value 1 (for one addition), is the representation of the trap or the normal value.
The emphasis is mine. Using trap representations is undefined behavior .
There are actual implementations that save this value as a default view of the trap . Noticeable I tend to refer to Unisys Clearpath Dordado on the OS2200 (go to 2-29) . Pay attention to the date indicated in this document; such implementations are not necessarily ancient (hence the reason why I quote this).
According to 6.2.6.2p4 , shifting negative values to the left is undefined behavior. I have not done much research on what behavior actually exists, but I would reasonably expect that there may be implementations that expand, as well as implementations that do not. This would also be one of the ways to form the trap representations mentioned above, which are undefined in nature and therefore undesirable. Theoretically (or perhaps some time in the distant or not so distant future), you may also encounter signals “corresponding to a computational exception” (that the standard category C, similar to the category in which SIGSEGV is located, corresponds to such things as “division” to zero ") or other erratic and / or undesirable behavior ...
In conclusion, the only reason the code in the question works is because it matches that the decisions your implementation made match correctly. If you use the implementation that I cited, you will probably find that this code does not work properly for some values.
Such heavy magic (as described in the comments) is actually not necessary, and in fact it does not look so optimal for me. If you want something that doesn't rely on magic (like something portable) to solve this problem, consider using this (in fact, this code will work at least 1 <= n <= 64 ):
#include <stdint.h> int fits_bits(intmax_t x, unsigned int n) { uintmax_t min = 1ULL << (n - 1), max = min - 1; return (x < 0) * min + x <= max; }