From: Right shifting negative numbers in C
Edit: According to the Section 6.5.7 of the latest draft standard, this behavior on negative numbers is implementation dependent:
The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
And, your implementation is probably doing an Arithmetic Shift with two's complement numbers
Operator >>
as Signed right shift or arithmetic right shift, shift all the bits to right a specified number of times. Important is >>
fills leftmost sign bit (Most Significant Bit MSB) to leftmost bit the after shift. This is called sign extension and serves to preserve the sign of negative numbers when you shift them right.
Below is my diagrammatic representation with an example to show how this works (for one byte):
Example:
i = -5 >> 3; shift bits right three time
Five in two's complement form is 1111 1011
Memory Representation:
MSB
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
7 6 5 4 3 2 1 0
^ This seventh, the left most bit is SIGN bit
And below is, how >>
works? When you do -5 >> 3
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
| \ \
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
Notice: the left most three bits are one because on each shift sign bit is preserved and each bit is right too. I have written The sign is propagated because all this three bits are because of sign(but not data).
[ANSWER]
In your output in
first Eight lines
~t is 0
==> t is FFFFFFFF
==> t is -1
(Note: 2's complement of -1 is FFFFFFFF
, because 1 = 00000001
, 1's complement of 1 is FFFFFFFE
, and 2's complement = 1's complement + 1 that is: FFFFFFFE
+ 00000001
= FFFFFFFF
)
So t
is always evaluated -1
in first eight times in loop. Yes, How ?
In for loop
for (i=120;i<140;i++){
t = (i - 128) >> 31;
values of i
for first eight time is i = 120, 121, 122, 123, 124, 125, 126 ,127
all eight values are less then 128. So return of (i - 128) = -8, -7, -6, -5, -4, -3, -2, -1
. hence in first eight times expression t = (i - 128) >> 31
shift-rights a negative number.
t = (i - 128) >> 31
t = -ve number >> 31
Because in your system int is of 4 bytes = 32 bits, all right most 31
bits are shift-out and loss and due to propagation of sign bit that is 1
for negative number all bits value becomes 1
. (as I have shown in above figure for one byte)
So for fist eight times:
t = -ve number >> 31 == -1
t = -1
and this gives
~t = 0
Hence output of fist eight times for ~t is 0.
For remaining last lines
~t is FFFFFFFF
==> ~t is -1
==> t is 0
For remaining last lines, in for loop
for (i=120;i<140;i++){
t = (i - 128) >> 31;
i values are 128, 129, 130, 132, 133, 134, 135, 136, 137, 138, 139,
all are greater then or equals to 128. and sign bit is 0
.
So (i - 128) for remaining last lines is >=0
and for all this MSB sign bit = 0
. And because again you shifts right 31 times all bits excepts then sigh bit shift-out and sign bit 0
propagates and fills all bits with 0
and magnitude becomes 0
.
I think it would be good if I write an example for a positive number too. So we take an example 5 >> 3
and five is one byte is 0000 0101
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
+----+----+----+---+---+---+---+---+
| \ \
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
See again I writes The sign is propagated, So leftmost three zeros are due to sign bit.
So this is what operator >>
Signed right shift do, and preserves the sign of left operand.