Reputation:
I don't understand what happens in this combination of unary operators exactly. I know that when you type it in, it will end up producing the smallest signed char value, what I don't understand is HOW exactly.
What I think the solution is ========================================================================
~ is a unary operator that effectively means the same as the logic operand 'NOT' right?
So, Not char means what? Everything in char is reduced to 0?
Is the char not being cast to the unsigned char?
then we cast the char to unsigned but everything that is not a 0 is moved over by 2^1 since >> 1 is the same thing as doing 2^1, right?
========================================================================
#include <stdio.h>
int main(){
printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >> 1));
return 0;
}
It produces the smallest signed char, which works, but I just want to know what's happening under the hood because it's not completely clear.
Upvotes: 1
Views: 499
Reputation: 4654
~
is not the logical NOT, it is the bitwise NOT, so it flips every bit independently.
~0
is all 1 bits, casting it to unsigned char and shifting once to the right makes the first bit 0. Casting to signed char and applying bitwise NOT makes the first bit 1 and the rest 0, which is the minimum value of a two's complement integer (this assumes that two's complement is used here, which isn't guaranteed by the standard).
The casts are needed to ensure that the shift will fill in the first bit with a 0 since on signed integers it is possible that an arithmetic shift is used which fills in the leading bits with the sign bit of the number (1 in this case).
Upvotes: 1
Reputation: 618
This code looked familiar, so I searched my ancient mail and found this macro:
#define MSB(type) (~(((unsigned type)-1)>>1))
in the .signature of Mark S. Brader.
It returns a value of the specified integer type whose bits are all zero except for the Most Significant Bit.
(unsigned char)-1
produces #FF(#FF)>>1
produces #7F~(#7F)
produces #80It so happens that #80 happens to be the smallest negative value for the given type (though in theory C isn't required to use 2s complement to store negative integers).
EDIT:
The original MSB(type) was intended to produce a value that would be assigned to a variable of type "type".
As @chux points out, if it's used in other contexts, it could extend extra bits to the left.
A more correct version is:
#define MSB(type) ((unsigned type)~(((unsigned type)-1)>>1))
Upvotes: 1