C is a very simple language (or so they say). Its design was based strongly on available hardware features, i.e. on ease of implementing the compiler. Indexing an array translates directly into pointer arithmetic, so:
int array[256]; int i = 10; ... array[i] = 12; translates into something like:
*(array + i*sizeof(int)) = 12; or in imaginary intermediate machine language:
load value of array into register Ra load value of i into register Rb right shift Rb by X number of bits add value in Rb to value in Ra store value 12 at address in Ra (Note: here array is the address fixed at load time, so I say "load value of array" - it's a bit different for indexing a pointer, one more indirection is required to obtain the base address.)
With this in mind zero-based indexing is only natural.