People have already mentioned (a) the lawyer's strict language interpreting the standard, and (b) the x86 segments, usually in 16-bit code (but also on some older 32-bit OSs).
Let me mention another example close to my heart:
Andy Gleu. 1990. An empirical study of indexing OR. SIGMETRICS Run. Eval. Rev. 17, 2 (January 1990), 41-49. DOI = 10.1145 / 378893.378896 http://doi.acm.org/10.1145/378893.378896
What am I.
In this article, I proposed a set of instructions that used the OR mode rather than ADD as the memory addressing mode.
Now, since C programmers can always do
int* a = new int[5] + 1;
compilers should handle these things correctly.
But at the same time, they may be less effective.
It turns out I'm not the only one who thought about this. Some real transport computers have used this technique, although I have no links.
Anyway, this is just an example.
In general, although
a) what you offer will work on most machines (of course, most machines are x86s running Windows or Linux or ARM, working with UNIX derivatives such as iOS and Android).
b), but it may be illegal. This may break some compiler optimizations, be interrupted by some compiler optimizations, etc.
By the way, on x86 1-based arrays cost a bit more code and almost nothing in machine code. If you say something like
template<typename T,uint size> class One_Based_Array { private: T array[size]; public: T& operator[](uint i) { return array[i-1]; } };
used as
One_Based_Array<int,100> a; int tmp = a[i];
machine code will look something like this:
MOV EAX, a.array-4(ebx)
i.e. 1-based things can usually be stacked in x86 basereg + indexreg + offset mode. On some machine it costs nothing, as a rule, although the code may be a bit more.
In fact, Intel compilers often generate code that looks like
ebx = -i MOV EAX, address_of_end_of_array[ebx]
i.e. using indexing with subtraction, and not with the addition, or with the addition of a negative number, since testing against 0 is more effective than testing against + N.