###### 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
```