配列とは結局こういうこと

配列の添字指定は「人間にとっての分かりやすい表現」であって、配列概念など知ったこっちゃない処理系は「ベースアドレス(先頭要素へのポインタ値)+要素サイズ*要素番号」という計算式で、配列の各要素にアクセスしているのです。配列が「先頭要素へのポインタ値」で管理されるのは、その配列が仮想アドレス空間上の連続した領域に確保されることが保証されているからであって、その前提があるのなら、以下のような邪悪なコードでもプログラムは動作します。

以下は、変数c1〜c6の領域が、「スタック上の連続した領域に、メモリアドレスの昇順で確保されている」前提で、c1領域のアドレスをベースとしたオフセット指定により、c1〜c6の各領域にアクセスしているコードです。変数c2〜c6は、「配列」領域を静的に確保するためだけに宣言したものであり、使用はしていません(スタックフレームのサイズはスタックポインタで調整されるので、動的確保とも言えますが)。

  1 #include <stdio.h>
  2
  3 int main(int argc, char **argv){
  4
  5     char c1 = 'A';
  6     char c2 = 'B';
  7     char c3 = 'C';
  8     char c4 = 'D';
  9     char c5 = 'E';
 10     char c6 = '\0';
 11     int i;
 12
 13     for(i=0; *((char *)&c1+i*sizeof(c1))!='\0'; i++)
 14         printf("%p : %c\n", (char *)&c1+i*sizeof(c1), *((char *)&c1+i*sizeof(c1)));
 15     printf("\n");
 16
 17     return 0;
 18 }

実行結果

0x7fff5d863b86 : A
0x7fff5d863b87 : B
0x7fff5d863b88 : C
0x7fff5d863b89 : D
0x7fff5d863b8a : E