Reputation: 1954
I found a program that prints the maximum and minimum values of a signed char. Though we've learned bit operations in class, I don't understand when all the operators are put together.
int main(void)
{
printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1);
printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1));
}
For instance, I know that ~ flips the bits and >> moves them over to the right. So I believe ~0 >> 1, flip all the bits and shift them to the right one spot. But why do we subtract 1, I thought two's complement adds one?
Upvotes: 2
Views: 502
Reputation: 181469
Taking the maximum first, adding parentheses to the original expression to clarify the order of operations, the original expression becomes
(char) (((unsigned char) (~0)) >> 1)
First, ~0
yields a value of type int
(because the constant 0
has that type) whose bit pattern consists of all 1
s (excluding any padding bits). This will be a negative number, because its sign bit will be set.
The cast converts that value to type unsigned char
, which results in a value of that type with all bits 1
.
But the type signed char
has exactly one fewer value bit than does unsigned char
, because its representation is the same size as that of unsigned char
, neither has any padding bits, and signed char
uses one of its bits as a sign bit. Shifting right one position shifts off the extra value bit, resulting in an unsigned char
whose value is the largest that can be accommodated by type signed char
.
The result is then cast to type char
, which is pointless. The value will be unchanged by the conversion, yet
char
is a different type from signed char
, and the former is not necessarily a signed type, so casting to char
cannot anyway serve any purpose related to the range of values of signed char
.
The resulting expression will be converted (further) to type int
prior to passing it to printf()
anyway.
Nevertheless, the value displayed is indeed the maximum value that is representable as a signed char
.
The expression for the minimum value simply yields one less than the inverse of the maximum. This is the correct minimum, provided that signed char
is represented in two's complement form. Although every modern implementation I know indeed does use two's complement form for signed integers, C explicitly allows two other forms, both of which sport minimum values equal to the inverse of their maximum values. The program would produce the wrong minimum value on a platform with such a representation of signed char
.
Upvotes: 1
Reputation: 42159
(unsigned char) ~0
has all bits 1 (largest positive unsigned char
)>> 1
turns off the highest bit, which is used for the sign (largest positive signed char
)-(char)
negates that value as a char
(note: should be signed char
)- 1
is used on the now-negative value because in two's complement the most negative value is one greater in magnitude than the most positive (because the value for zero has the sign bit off, and there is no "negative zero" in two's complement)Upvotes: 1
Reputation: 521
There is a -
operator in front of the expression that is used to compute the minimum value:
-(char)((unsigned char) ~0 >> 1) - 1
So the order of the operands evaluation in your expression is:
~0 >> 1
and cast the result to unsigned char
,char
,-
operator and-1
) to obtain the minimum possible value (the 0
value is considered as positive value).Upvotes: 0
Reputation: 1563
Because zero is considered positive, so there are 128 positive values 0 to 127 However negative starts from -1 so it has 128 negative values -1 to - 128.
Putting it shortly positive starts from 0 so it gets only to 127 however negative starts from -1 so it gets to -128
This is why 0111111 = 127 but 1000000=-128;
Upvotes: 0