【基本】C言語のポインタの説明

#はじめに
ポインタの基本から、関数へのポインタ渡しまでをなるべく行間を作らず解説します。
#ポインタとは
まず下のコードをご覧ください。

```c
#include <stdio.h>

int main(){
   int i;
   i = 1;
   printf("%d\n", i);
}
```
実行結果

```
1
```
このコードでは、まず```int i```で整数型変数```i```が生成され、メモリ領域が割かれます。そして```i=1```でそのメモリ領域に```1```というデータが保存されます。
ポインタとは、```i```のような変数が記憶されるメモリ領域の住所のことです。ポインタを得るには変数の前に```&```を付けて```&i```とします

```c
#include <stdio.h>

int main(){
   int i = 1;
   printf("%p\n", &i); //ポインタの指定変換文字はp
}
```
実行結果

```
0061FF2C
```
#ポインタ変数
上の実行結果の```0061FF2C```を保持する変数が必要になるときもあるでしょう。そのような変数は、ポインタを保持する変数なのでポインタ変数と呼ばれます。ポインタ変数の型は```変数の型*```で宣言します。例えば```int```型の変数へのポインタ変数は```int*```で、```char```型の変数へのポインタ変数は```char*```で宣言します。

```c
#include <stdio.h>

int main(){
   int i = 1;
   int* pointer; //int型のポインタを宣言
   pointer = &i;
   printf("%p\n", &i);
   printf("%p\n", pointer);
}
```
実行結果

```
0061FF28
0061FF28
```

何故ポインタ変数の宣言で、元の変数の型を指定する必要があるのでしょうか？それはメモリの仕組みと関係しています。メモリには、1バイトずつ、固有の住所が割り当てられています。それが上の```0061FF28```などの16進整数です。```int```型の変数は4バイトのデータをもつのでメモリ領域は```0061FF28, 0061FF29, 0061FF2A, 0061FF2B```の4つです。しかし、4つも住所を扱うのは大変ですから、「```0061FF28```から連続した4バイト分の領域」として扱います。バイト数は変数の型によって違いますから、ポインタ変数を宣言する際に、変数の型の情報が必要だということです。

なお、上のコードの

```c

int* pointer;
pointer = &i;
```
は

```c

int* pointer = &i;
```
と一行に書き換えることができます。

ポインタ変数の前に```*```を付けると、ポインタ変数から元の変数にアクセスすることができます。

```c

#include <stdio.h>

int main(){
   int i = 1;
   int* pointer = &i;
   printf("%d\n", *pointer);
}
```
実行結果

```
1
```
実は```*pointer```は```i```とまったく同じように扱えます。```*pointer```に値を代入すると、```i```に代入したことになります。

```c

#include <stdio.h>

int main(){
   int i = 1;
   int* pointer = &i;
   *pointer = 2;
   printf("%d\n", i);
}
```
実行結果

```
2
```

#ポインタ演算
ポインタに整数を足し引きすることができます。
```int```型のポインタの場合、ポインタに1を足すと4バイト分だけポインタが移動します。これは、```int```型が4バイト分のメモリ領域をもつからです。

```c

#include <stdio.h>
int main(){
   int i = 1;
   int* pointer = &i;
   printf("%p\n", pointer);
   pointer++; //ポインタを移動する
   printf("%p\n", pointer);
}
```
実行結果

```
0061FF28
0061FF2C
```

16進数なので```0061FF28+4=0061FF2C```となります。

#配列とポインタ
配列の要素は連続したメモリ領域に記憶されており、ポインタを用いて配列を操作することができます。要素がn個ある配列```i[n]```の```i```は、実は先頭の配列要素```i[0]```へのポインタとなっています。

```c
#include <stdio.h>

int main(){
   int i[3]={1, 2, 3};
   printf("%p\n", i);
   printf("%d\n", *i);
}
```
実行結果

```
0061FF24
1
```
ここで、```0061FF24```は配列の先頭要素である```1```へのポインタです。
```i```のポインタ演算も行うことができます。

```c
#include <stdio.h>

int main(){
   int i[3]={1, 2, 3};
   printf("%d\n", *i);
   printf("%d\n", *(i+1)); //i+1は配列2番目要素を指すポインタ。*演算子で値にアクセス
   printf("%d\n", *(i+2));
}

```
実行結果

```
1
2
3
```

ただし```i```はポインタ変数でないことに注意が必要です。ポインタ変数はポインタを保持する変数であるので、保持している値(=ポインタ)を変えることができます。一方で```i```はポインタ変数でないので、ポインタを変えてしまうような操作、例えば```i++```などはできません。

上の例をみると、```i[k]```と```*(i+k)```は同じ意味をもつことがわかります。実は```i[k]```よりも、```*(i+k)```のほうがより本質的な記述であり、```i[k]```は便宜的な記法にすぎません。このことを```i[k]は*(k+1)```のシンタックスシュガーであるといいます。

#関数へのポインタ渡し
これまでに紹介したポインタの原理を使うと関数から複数の返り値を受け取ることができます。

```c
#include <stdio.h>

//2つの引数をそれぞれ0, 1にする関数
void zero_one(int* l, int* m){  //ポインタ変数l, mがポインタを受け取る
    *l=0; //*演算子で値にアクセス
    *m=1;
}
int main(){
    int i=2, j=3;
    zero_one(&i, &j);  //ポインタを渡す
    printf("%d/t%d\n", i, j);
}
```
実行結果

```
0    1
```

関数に配列を渡すこともできます

```c
#include <stdio.h>

//配列の最初の要素を0に、2番目の要素を1にする関数
void zero_one(int* p){ //ポインタ変数pがポインタを受け取る
	p[0] = 0; //*p=0と同値
	p[1] = 1; //*(p+1)=1と同値
}

int main(){
   int i[2] = {2, 3};
   zero_one(i); //ポインタを渡す。配列iはポインタになってる！
   printf("%d\t%d\n", i[0], i[1]);
}
```

実行結果

```
0    1
```

#おわりに
間違った記述があればご指摘お願いいたします。