配列の場合、なぜ a[5] ==5[a] になるのですか?

C 標準は [] を定義します 演算子は次のとおりです:

a[b] == *(a + b)

したがって a[5] 次のように評価されます:

*(a + 5)

5[a] 次のように評価されます:

*(5 + a)

a 配列の最初の要素へのポインタです。 a[5] 5 要素の値です a からさらに 、これは *(a + 5) と同じです であり、小学校の数学から、それらが等しいことがわかっています (足し算は可換です)。


配列アクセスはポインターの観点から定義されているためです。 a[i] *(a + i) を意味するように定義されています 、可換です。


他の回答では何かが見落とされていると思います.

はい、p[i] 定義上、*(p+i) と同等です 、これは (加算は交換可能であるため) *(i+p) と同等です 、これ (再び、[] の定義による) operator) は i[p] と同等です .

(そして array[i] で 、配列名は配列の最初の要素へのポインターに暗黙的に変換されます。)

しかし、この場合、足し算の可換性はそれほど明白ではありません。

両方のオペランドが同じ型である場合、または共通の型に昇格された異なる数値型であっても、可換性は完全に理にかなっています:x + y == y + x .

しかし、この場合は、1 つのオペランドがポインターで、もう 1 つのオペランドが整数であるポインター演算について具体的に話しています。 (整数 + 整数は別の演算であり、ポインタ + ポインタはナンセンスです。)

+ の C 標準の説明 オペレーター (N1570 6.5.6) のコメント:

次のように簡単に言えます:

この場合、両方の i + pi[p]

C++ の用語では、オーバーロードされた + のセットが 2 つあります。 大まかに次のように説明できる演算子:

pointer operator+(pointer p, integer i);

そして

pointer operator+(integer i, pointer p);

そのうち、本当に必要なのは最初の 1 つだけです。

では、なぜこのようになっているのでしょうか?

C++ はこの定義を C から継承し、C は B から取得しました (配列のインデックス付けの可換性は、1972 年の B へのユーザー リファレンスで明示的に言及されています)。BCPL から取得しました (1967 年のマニュアル)。以前の言語 (CPL? Algol?)

したがって、配列のインデックス付けは加算によって定義され、ポインターと整数の加算でさえ交換可能であるという考えは、何十年も前の C の祖先言語にまでさかのぼります。

これらの言語は、現代の C よりもはるかに型付けが厳しくありませんでした。特に、ポインターと整数の違いはしばしば無視されていました。 (初期の C プログラマーは、unsigned の前に、ポインターを符号なし整数として使用することがありました。 キーワードが言語に追加されました。) したがって、オペランドの型が異なるために加算を非可換にするという考えは、おそらくこれらの言語の設計者には思いつかなかったでしょう。ユーザーが 2 つの「もの」を追加したい場合、それらの「もの」が整数、ポインター、またはその他のものであるかどうかにかかわらず、それを防ぐのは言語次第ではありませんでした。

そして何年にもわたって、そのルールを変更すると、既存のコードが壊れていました (ただし、1989 年の ANSI C 標準は良い機会だったかもしれません)。

C および/または C++ を変更して、ポインターを左側に、整数を右側に配置する必要があるようにすると、既存のコードが壊れる可能性がありますが、実際の表現力が失われることはありません。

これで arr[3] になりました と 3[arr] まったく同じことを意味しますが、後者の形式は IOCCC の外に出てはなりません。