maddie
maddie

Reputation: 1954

Bitwise operations w/ signed chars

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

Answers (4)

John Bollinger
John Bollinger

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 1s (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

  1. 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.

  2. 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

Arkku
Arkku

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

acornagl
acornagl

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:

  1. Compute ~0 >> 1 and cast the result to unsigned char,
  2. Cast the previous result to char,
  3. Change the sign of the previous result by using the - operator and
  4. Subtract one (-1) to obtain the minimum possible value (the 0 value is considered as positive value).

Upvotes: 0

O_Z
O_Z

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

Related Questions