ポインタ変数とポインタのポインタ
ポインタ変数の宣言
char *a[];
をしたとき僕の中では
a[0],a[1]...という、ある文字列A,B,C...の最初のアドレスを指すポインタが、配列になっているものを宣言していると理解していました。
しかしこの次に、ポインタのポインタが出てきました。僕はこれを、
ある変数を指し示すアドレスのアドレスである、と理解しました。
この2つは1つめはいくつかのアドレスを指し示すもの、2つ目は1つのアドレスを指し示すものであるとして、僕の中で異なったものであると理解していましたが、参考書「C標準コースウェア」によると
プログラムにおいて、関数でポインタ配列を受け取るときchar *p[]はchar **pとしてもよい
と書かれており、またその実例として、
(9-5)
#include <stdio.h>
void disp (char *p[],int n){
int i;
for (i= 1;i<n;i++){
printf("%s\n",p[i]);
}
}
int main(void){
char *girl[] = {"Arica","Candy","Lisa"};
disp (girl,sizeof(girl)/sizeof(girl[0]));
return 0;
}
というプログラムが書かれていました。
ここで一気に訳が分からなくなりました。
char *girl[] = {"Arica","Candy","Lisa"};
と宣言されているため、
girl[0]はAricaという文字列の最初のアドレスを指すポインタ、
*girl[0]はAricaという文字列を直接指し示していると解釈しています。
girlは{"Arica","Candy","Lisa"}という文字列の配列の最初のアドレスを指し示していると考えました。
sizeof(girl)を使った時に不思議なのですが、
girlはどのように配列の終わりを理解しているのでしょうか?
(配列の要素数を渡していない点が不思議です。)
また、
disp側が受け取ったのは*girl[]であり、いくつかのポインタの配列ですが、渡したものはgirlという要素数がないポインタ1つだけです。
そして最初の疑問が出てくるわけですが、*p[]を**pと書きかえてみると、
文字列のアドレスを示すgirlという名の1つのポインタを渡すと、pという名のポインタのポインタで受け取るというのも、よくわからなくなっています。
おそらくポインタ配列に対する理解がどこかでずれているようですが、自分でどこがわからないのかわからなくなっています。
どうかご教授ください。
お礼
わかりやすい図での解説、ありがとうございます。 今までメモリ領域のことを棒グラフのように直線状だと思い込んでいましたが、 バイトの存在をすっかり忘れておりました。 ここで気づくことができてよかったです。 >a[0]が0x12345678という値だった場合 お礼欄に質問を書くのもどうかと思うのですが、 0xと12345678の関係がよくわかりません。(無知ですみません・・・) 今までは1001とか、1002などの単純な数字のアドレスしか見たことがなかったもので・・・ 簡単でいいので、ご説明願えませんでしょうか。 >「普通は」とあるのは、そうならない場合もあるということです。 >具体的には、sizeof演算子や&演算子のオペランド(演算対象)になった場合です。 sizeof演算子や&演算子のオペランド(演算対象)はまだ習っていないのでよくわかっていないのですが、 必ずしも先頭要素=先頭アドレスではないということはわかりました。 今後sizeof演算子等を勉強する際の参考にさせていただきます。 このたびはどうもありがとうございました。