他の回答では何かが見落とされていると思います。
はい、p[i]
定義によりと同等です*(p+i)
(これは加算が可換であるため)はと同等です*(i+p)
(これも[]
演算子の定義による)はと同等i[p]
です。
(およびでarray[i]
は、配列名は暗黙的に配列の最初の要素へのポインターに変換されます。)
しかし、この場合、加算の交換可能性はそれほど明白ではありません。
両方のオペランドが同じ型の場合、または共通の型に昇格された異なる数値型の場合でも、可換性は完全に理にかなっていますx + y == y + x
。
ただし、この場合は、1つのオペランドがポインターで、もう1つのオペランドが整数であるポインター演算について具体的に説明します。(整数+整数は別の操作であり、ポインター+ポインターは無意味です。)
+
オペレーターに関するC標準の説明(N1570 6.5.6)は次のように述べています。
さらに、両方のオペランドが算術型であるか、一方のオペランドが完全なオブジェクト型へのポインタであり、もう一方が整数型である必要があります。
それは同じくらい簡単に言ったでしょう:
さらに、両方のオペランドが算術型であるか、左の
オペランドが完全なオブジェクト型へのポインタであり、右のオペランド
が整数型である必要があります。
その場合、i + p
との両方i[p]
が違法になります。
C ++の用語では、実際には2つのオーバーロードされた+
演算子のセットがあり、大まかに次のように説明できます。
pointer operator+(pointer p, integer i);
そして
pointer operator+(integer i, pointer p);
最初のものだけが本当に必要です。
では、なぜこのようになるのでしょうか。
C ++はこの定義をCから継承し、Bから取得しました(配列のインデックス付けの可換性は、1972年のユーザーズリファレンスのBで明示的に言及されています)。BCPLから取得しました。以前の言語(CPL?Algol?)。
したがって、配列のインデックス付けは加算の観点から定義されており、その加算はポインタと整数であっても交換可能であり、Cの祖先言語に何十年も遡ります。
これらの言語は、現代のC言語よりも強く型付けされていません。特に、ポインタと整数の違いはしばしば無視されました。(初期のCプログラマは、unsigned
キーワードが言語に追加される前に、ポインタを符号なし整数として使用することがありました。)したがって、オペランドが異なる型であるため、加算を非可換にするという考えは、おそらくそれらの言語の設計者には思い浮かばなかったでしょう。ユーザーが2つの「もの」を追加したい場合、それらの「もの」が整数、ポインター、またはその他のものであるかどうかにかかわらず、それを防ぐのは言語の責任ではありませんでした。
そして、何年にもわたって、そのルールに変更を加えると既存のコードが壊れてしまいます(1989年のANSI C規格が好機だったかもしれませんが)。
ポインターを左側に配置し、整数を右側に配置する必要があるようにCまたはC ++を変更すると、既存のコードが壊れることがありますが、実際の表現力は失われません。
つまり、後者の形式はIOCCCの外部に表示されるべきではありませんが、まったく同じことarr[3]
を3[arr]
意味します。