###### tags: `C` # 添字演算子について [] ←コレ (C言語) ### 前提知識:配列名の正体 ```c int a[n]; ``` `a`←これは、配列0番目のポインタだ つまり、以下が言える ```c int a[3] = {1,2,3}; int *p = a; // この時、a と pは等価である。 ``` では、`a[i]`これはなんだろう? 結論から述べると、 `ポインタ:aにiを加算したアドレスのエイリアス`だ #### エイリアス・・・?ってなれば、こちらも読んで欲しい ポインタのおさらいもしておく。 関節演算子`*`でポインタを操作すると、参照しているオブジェクトの実体を得ることができる。 ```c int a=4; int *p = &a; // 式:&a は aのポインタを返す // この時、 // 式:p はaのアドレスを返す。 // 式:*p はアドレスが指しているオブジェクト:a を返す。 // なので、a と *p は等価だ。 ``` ということがわかる。 つまり、`*p`は`a`の別名(エイリアス)なのだ。 で、`a[i]`に話を戻す。先ほど述べた `ポインタ:aにiを加算したアドレスのエイリアス`をコードで表すと `ポインタ:aにiを加算したアドレス` = `a+i` `のエイリアス` = `*(a+i)` と、表すことができる `a[i] = *(a+i)`が言える。 ```c int a[3] = {1,2,3}; int *p = a; // p == a // a[i] == *(a+i) ``` ### 演算子の正体 そもそも、添字演算子は二項演算子であり、オペランドを二つ受け取る。 そして、任意の型のオブジェクトを返す。 オペランドは * オブジェクトへのポインタ * 汎整数型 でなくてはならない しかし、交換することは可能だ。(足し算の交換法則の`交換`と同じ意味。) ```c int n = 2; int a[3] = {1,2,3}; // a は オブジェクト(配列)へのポインタ a[n]; // n は 汎整数型 ``` `[]`演算子は挙動から察するに **a というアドレスに n という差分のアドレス足し込んでいるにすぎない(n+a)** *(少し、具体的にいうと、`a + (n * intのサイズ)` いずれにせよ、交換できる)* なので、当然、これらは単純な足し算であり、交換をしても問題がない。 なので、`n[a]`と表現もすることができる。 以下、サンプルコード ```c= #include<stdio.h> int main(){ int a[3] = {1,2,3}; for(int i = 0;i<3;i++){ printf("a[%d] = %d ,",i,a[i]); printf("%d[a] = %d\n",i,i[a]); // <-- } } ``` 僕の実行系における出力 ``` a[0] = 1 ,0[a] = 1 a[1] = 2 ,1[a] = 2 a[2] = 3 ,2[a] = 3 ```