Left-shifting -1
2 bits yields -4
, which is the correct byte offset to add to get the -1st position.
Left-shifting will only yield a positive number if i
is extremely large such that the result overflows. But that could only happen if you were trying to access beyond the -229th index (assuming 32-bit int
s), which is of course too large (small?) of an index to ask for in the first place.
By the way, accessing a negative index is only valid if you're starting with a pointer that's midway through an object and the negative index is still accessing valid memory. A[-1]
would invoke undefined behavior. A better example would be:
int *p = &A[3];
int i = -1;
int test = p[i];
Here p[-1]
resolves to (&A[3])[-1]
which is equivalent to A[2]
. That's a valid index, so p[-1]
is legal.
Also, while in assembly code it's fine, it should be noted that left shifting negative numbers in C is undefined. Don't try to write -1 << 2
in your C code. The compiler can do it on our behalf but we're not allowed to write it ourselves.
What if you shift 100001
one time to the left? You will get 000010
, which is positive in my books.
That would only be the case if int
s were 6-bits wide. Per the C standard they must at least 16-bits wide, and in modern computers are usually 32-bits, and sometimes 64.
Let's say we were on a 16-bit system. 100001
would actually be one of these two numbers:
0000000000100001
. This is 33, a positive number.
1111111111100001
. This is -31, a negative number. Shifting it left would retain all but one of the leading 1
bits and remain negative.