I need to find the most significant bit of signed int N and save it in signBitN. I want to do this using bitwise only operations. Also, how would I make signBitN extend so that all its bits are equal to its significant bit. i.e. if it's significant bit was zero, how would I extend that to be 00000...00? The closest I've gotten is signBitN=1&(N>>(sizeof(int)-1));
-
What is N? Do you want to find the sign bit of a particular type, like `int` or `int16_t`? – Eric Postpischil Feb 28 '21 at 22:06
-
shift by `(CHAR_BIT*sizeof(int)-1)` – tstanisl Feb 28 '21 at 22:06
-
1There's no particular benefit of doing this with bitwise operators over the obvious `(N < 0)` or `(N < 0) ? -1 : 0`. If there are clever bitwise approaches, let your compiler's optimizer insert them for you. [Example](https://godbolt.org/z/Yoesh3). – Nate Eldredge Feb 28 '21 at 22:06
-
N is a signed int – Future-Escape5902 Feb 28 '21 at 22:30
-
Are you asking what is the most significant bit position, or do you want to find the first `1`? – stark Feb 28 '21 at 23:15
-
I want the bit at the most significant position – Future-Escape5902 Mar 01 '21 at 01:01
2 Answers
Portable expression:
1 & (x >> (CHAR_BIT * sizeof(int) - 1))
Latest C standards put 3 standards on representation of ints.
- sign and magnitude
- one complement
- two complement
See section
6.2.6.2 Integer types
of C11 standard.
Only the third option is relevant in practice for modern machines.
As specified in 6.2.6.1
:
Values stored in non-bit-field objects of any other object type consist of n x CHAR_BIT bits, where n is the size of an object of that type, in bytes.
Therefore int
will consist of sizeof(int) * CHAR_BIT
bits, likely 32.
Thus the highest bit of int
can be read by shifting right by sizeof(int) * CHAR_BIT - 1
bits and reading the last bit with bitwise &
operator.
Note that the exact value of the int
after the shift is implementation defined as stated in 6.5.7.5
.
On sane machines it would be:
int y = x < 0 ? -1 : 0;
The portable way would be casting between int
and an array of unsigned char
and setting all bytes to -1
.
See 6.3.1.3.2
:
if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
And 6.2.6.1.2
Values stored in unsigned bit-fields and objects of type unsigned char shall be represented using a pure binary notation.
You can use memset()
for that.
int x;
memset(&x, (x < 0 ? -1 : 0), sizeof x);

- 13,520
- 2
- 25
- 40
-
1If `x` is negative then `x >>` has an implementation-defined result. Some implementations may fill with zero bits , for example. – M.M Feb 28 '21 at 22:27
-
@M.M, yes it's implementation defined. But the question was about value of the highest bit *before* shifting – tstanisl Feb 28 '21 at 22:32
-
The entirety of the result is implementation-defined ; the standard doesn't guarantee that your first suggestion will give the right answer . So perhaps "portable" is not a good description of that code. – M.M Feb 28 '21 at 22:57
-
@M.M Yes. The result of the operation is implementation defined because the bit representation of 'int' is implementation defined. Maybe first the concept of the highest bit should be defined. – tstanisl Feb 28 '21 at 23:02
-
If the question is how to check the MSB bit of the integer (for example 31st bit of the 32 bit integer) ten IMO this is portable.
#define MSB(i) ((i) & (((~0U) >> 1) ^ (~0U)))
#define issetMSB(i) (!!MSB(i))
int main(void)
{
printf("%x\n", MSB(-1));
printf("%x\n", issetMSB(-1));
}

- 60,014
- 4
- 34
- 74
-
...if "cast to unsigned" is one of the allowed operations (not clear from the OP) – M.M Feb 28 '21 at 23:37
-
1@M.M is cast in not allowed then it is not possible in the portable C. – 0___________ Feb 28 '21 at 23:40
-