size_t is usually defined as unsigned. When you compare a signed and unsigned number or an equal rank, the signed number is converted to unsigned. Since the signed number is probably presented in two additions in your machine, the negative numbers are actually larger.
So, once i reaches -1, this is more than the comparison thinks that it is more than len.
You can see this happening by turning on the warning in your compiler.
Compiling your program with clang -Weverything produces this warning
unsigned.c:10:30: warning: comparison of integers of different signs: 'int' and 'size_t' (aka 'unsigned long') [-Wsign-compare]
source share