This is a nice question. It had me thinking for a bit. So let's see what's going on here.
sizeof(i) returns the size of the variable i. This wold typically be 4 bytes as int typically means a 32-bit integral number.
so your loop would be this
for (i = -1; i < 4; i++)
So why do we not enter the loop?
It is, because we have forgotten about types!
i is of type signed 32-bit int.
sizeof(i) returns a type size_t, which is typically an unsigned 64-bit int.
The computer cannot compare signed and unsigned types without casting one to the other and since the unsigned 64-bit int is larger than the signed 32-bit int, that will be the type.
So the loop actually looks like this:
for (int i = -1; (unsigned long int)i < 4ul; i++)
4ul is the numeric literal 4 with the type of unsigned long int.
So the question is, what happens when you cast a signed int to an unsigned long int?
-1 is 0xFFFFFFFF (See how signed numbers work.)
But if you look at 0xFFFFFFFF as an unsigned number, then it is 4,294,967,295.
So the loop really is
for (i = 4294967295; i < 4; i++)
Now, it's not surprising that we never enter the body of the loop.
I hope this helped. Keep on coding! :)