【ポインタ=番地?】
前回のパターン2の続きです。下記のように宣言していました。
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ int* a; ┃
┃ int b[100]; ┃
┃ ┃
┃ a = &b[0]; /* int型の配列bの先頭アドレスが a に代入される。*/ ┃
┃ /* ちなみに、配列は[]を省略すると番地を示すので */ ┃
┃ /* a = b */ ┃
┃ /* と表記しても同じ。 */ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
ポインタ変数aに配列(b[100])の先頭アドレスを代入しています。
図に表すと以下のようなります。 ( ※int を4バイトとして考えています。 )
ポインタ変数 a 配列 b[100]
┏━━━━━━┓ ┏━━━━━━┓
┣ ┫ ┣ ┫
┣ ┫ ┣ b[0] ┫
┣ ┫ ┣ ┫
┗━━━━━━┛ ┣━━━━━━┫
┣ ┫
┣ b[1] ┫
┣ ┫
┣━━━━━━┫
┃ : ┃
┃ : ┃
┃ : ┃
┃ : ┃
┣━━━━━━┫
┣ ┫
┣ b[98] ┫
┣ ┫
┣━━━━━━┫
┣ ┫
┣ b[99] ┫
┣ ┫
┗━━━━━━┛
b[100] と宣言すると配列で使用できる添え字は0〜99の100個です。
C言語の添え字は0から始まります。
ここで、便宜上 配列bの先頭アドレスを100番地とすると、図は以下のように
なります。
ポインタ変数 a アドレス 配列 b[100]
a ┏━━━━━━┓ 100 ┏━━━━━━┓
┣ ┫ ┣ ┫
┣ 100 ┫ ┣ b[0] ┫= *(a + 0)
┣ ┫ ┣ ┫
┗━━━━━━┛ 104 ┣━━━━━━┫
┣ ┫
┣ b[1] ┫= *(a + 1)
┣ ┫
108 ┣━━━━━━┫
: ┃ : ┃
: ┃ : ┃
: ┃ : ┃
: ┃ : ┃
392 ┣━━━━━━┫
┣ ┫
┣ b[98] ┫= *(a + 98)
┣ ┫
396 ┣━━━━━━┫
┣ ┫
┣ b[99] ┫= *(a + 99)
┣ ┫
┗━━━━━━┛
前回、
「ポインタ変数の頭に *(アスタリスク)をつけると番地の内容を示す」
と書きましたね?
今回もその法則が適応されます。つまり。
「*a の値と b[0] の値は同じ」
ということが言えます。
少し見方を変えてみると以下のように見ることができます。
「*(a+0) の値と b[0] の値は同じ」
そして、
「*(a+n) の値と b[n] の値は同じ」 (nは0からの整数)
とも、言うことができます。
ここで、疑問があがります。
「変数aの値は 100(番地)なのに、+1 をすると b[1] (104番地)の内容を示している??」
→ ここが、C言語のポインタと番地(アドレス)の違いなのです!
ポインタ変数の +1 は配列との互換性を保つため型のサイズ分アドレスが加算されます。
ここではintを4バイトとしているので、アドレスが +4 されて b[1] と *(a+1)の
内容が一致するわけです。
この部分が通常の変数とポインタ変数の違いなんです。
もし、変数aがchar型のポインタ変数 ( char* a ) で宣言されて、
配列bがchar型の配列 (char b[100]) で宣言されていた場合は
a = 100 番地と仮定すると charのサイズ は 1バイトなので
a + 1 = 101 (番地)
a + 2 = 102 (番地)
a + 3 = 103 (番地)
: :
: :
: :
と、内部的にアドレスが計算されます。
もちろん、short型のポインタ変数 (short* a) ならば、
short型 のサイズ は 2バイトなので
a + 1 = 102 (番地)
a + 2 = 104 (番地)
a + 3 = 106 (番地)
: :
: :
: :
となっていきます。
もちろん、このアドレス計算はコンパイラが自動的に行ってくれるので
プログラマはアドレス計算を意識せずにプログラムを組めるわけです。
【今回のまとめ】
・ポインタと配列は等価に扱うことができる。
・ポインタ変数の加算・減算は型のサイズに依存する。