2次元配列aのaは2次元配列の配列変数の先頭の配列変数a[0][0]のアドレスを格納するポインタ変数のアドレスを格納するポインタ変数となります

ソーラー「さあて


            char **k;


を実行して


char型の変数のアドレスを格納することができるポインタ変数のアドレスを格納することのできるポインタ変数


             k


を作製することができました


おもしろくなってきたね」



アレサ「宝物のような


めずらしいポインタ変数さんですね」


ソーラー「そうだね


char型の変数のアドレスを格納することができるポインタ変数のアドレスを格納することのできるポインタ変数


             k



の使い方は後ほど考察するとして



お話はちょっとかわって


1次元配列宣言、初期化


char a[3]="aa";


を実行したなら


配列変数


a[0]

a[1]

a[2]


が生成され


配列変数


a[0]

a[1]

a[2]

文字データ


'a'

'a'

'\0'



a[0]='a';

a[1]='a';

a[2]='\0';

のように

格納されましたね


このとき


1次元配列aにより生成される配列変数の


先頭の配列変数a[0]のアドレスを格納しているポインタ変数



a


でした


そのとき


          printf("%s\n", a);


を実行すれば



文字列


aa


をコマンドプロンプト画面に表示することができます


そのプログラムはこちらです

👇

#include <stdio.h>


int main() {


char a[3]="aa";


printf("%c\n", a[0]);

printf("%c\n", a[1]);

printf("%c\n", a[2]);

printf("%s\n", a);


return 0;


ビルド実行結果


a

a

(空白)

aa




そして




2次元配列宣言、初期化


char a[3][3]={"aa","bb","cc"};


を実行したなら


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]



が生成され


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]


文字データ


'a'

'a'

'\0'

'b'

'b'

'\0'

'c'

'c'

'\0'

a[0][0]='a';

a[0][1]='a';

a[0][2]='\0'

a[1][0]='b';

a[1][1]='b';

a[1][2]='\0';

a[2][0]='c';

a[2][1]='c';

a[2][2]='\0';

代入することができました」


アレサ「はい、ソーラーさん


このとき


2次元配列aにより生成される配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]



先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数



なぜだかわかりませんが


🌞 *a🌞


でした



        💖*aはポインタ変数となっています💖


💖なぜ*aはポインタ変数となるのかは次のエピソードで解説されます💖


ここで


*aからaを取り除いた


aもポインタ変数とおもわれますの


💖なぜaもポインタ変数になるのかも次のエピソードで解説されますっちゃ💖



なぜなら


アスタリスク演算子*が*aのように


aに作用していますが


アスタリスク演算子*は


ポインタ変数にしか作用することができないからです



ポインタ変数aに*を用いた*aは


ポインタ変数aに格納されているアドレスのメモリにアクセスし


そのメモリに格納されているデータを表すことができました


逆に


*aから*を取り除いたaは


*aのアクセスしているメモリのアドレスを格納しているポインタ変数


となりました(´▽`*)


例えば


char* a='c';


により生成されるポインタ変数aに*を作用させた*aは


ポインタ変数aに格納されているアドレスのメモリにアクセスし


そのメモリに格納されている文字データ'c'を表しました


*a='c'


すなわち


*aは文字データ'c'をあらわしているというわけです


*aから*を取り除いたaは


*aのアクセスしているメモリのアドレスを格納するポインタ変数


つまり


文字データ'c'を格納しているメモリのアドレスを格納するポインタ変数

となります


逆に


aにアスタリスク演算子*を作用させた*aは


文字データ'c'を格納しているメモリにアクセスするので


*a='c'


*aは文字データ'c'をあらわすことになります



そして


2次元配列aの

配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]




💖先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数💖




                *a


でした


そして


先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数*a


の管理しているメモリにもアドレス番号がついています


となると


そのポインタ変数*aのアドレスを格納することのできるポインタ変数が


存在するわけです


ポインタ変数*aのアドレスを格納することのできるポインタ変数は



*aから*を取り除いた



                a


となります


ポインタ変数aが


先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数*aの


メモリのアドレスを格納しているからこそ


ポインタ変数aにアスタリスク演算子*を作用させた


*aは


先頭の配列変数a[0][0]のアドレスをあらわすことになります


(*´▽`*)うふふ・・・







solarplexuss「うむ うむ」



ソーラー「


それでは実際に


2次元配列宣言


char a[3][3]={"aa","bb","cc"};


を実行して


2次元配列aを作製し


生成される


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]



文字データ

'a'

'a'

'\0'

'b'

'b'

'\0'

'c'

'c'

'\0'

a[0][0]='a';

a[0][1]='a';

a[0][2]='\0'

a[1][0]='b';

a[1][1]='b';

a[1][2]='\0';

a[2][0]='c';

a[2][1]='c';

a[2][2]='\0';


のように代入してみたいと思います


このときの



a





2次元配列aの

配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]




💖先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数*aのアドレス💖


を格納しているポインタ変数となります


そのプログラムはこちらです

👇

#include <stdio.h>


int main() {


char a[3][3] = { "aa","bb","cc" };


printf("%c\n", a[0][0]);

printf("%c\n", a[0][1]);

printf("%c\n", a[0][2]);

printf("%c\n", a[1][0]);

printf("%c\n", a[1][1]);

printf("%c\n", a[1][2]);

printf("%c\n", a[2][0]);

printf("%c\n", a[2][1]);

printf("%c\n", a[2][2]);


return 0;


}


ビルド実行結果


a

a

(空白)

b

b

(空白)

(空白)


ソーラー「このときの


2次元配列aの


a



2次元配列aの

配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]




💖先頭の配列変数a[0][0]のアドレスを格納しているポインタ変数*aのアドレス💖


を格納しているポインタ変数となります


ということは


2次元配列aの

配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]



先頭の配列変数a[0][0]のアドレスを表示したければ


             *a


に%p出力変換指定子を用いて


printf("%p\n", *a);


を実行すればよいことになります


そのプログラムはこちらです

👇

#include <stdio.h>


int main() {


char a[3][3] = { "aa","bb","cc" };


printf("%c\n", a[0][0]);

printf("%c\n", a[0][1]);

printf("%c\n", a[0][2]);

printf("%c\n", a[1][0]);

printf("%c\n", a[1][1]);

printf("%c\n", a[1][2]);

printf("%c\n", a[2][0]);

printf("%c\n", a[2][1]);

printf("%c\n", a[2][2]);


printf("%p\n", *a);👈🌞ここです


return 0;


}


ビルド実行結果


a

a

(空白)

b

b

(空白)

(空白)

0052FDE0👈🌞ここです


ソーラー「配列変数a[0][0]のアドレスは0052FDE00ですね(^_-)-☆」


アレサ「なるほどですの


ソーラーさん


では


ポインタ変数である*aに


%s出力変換指定子を用いて


printf("%s\n", *a);


を実行したなら


コマンドプロンプト画面には何が表示されるのですか?」


ソーラー「今のプログラムでは


char a[3][3]={"aa","bb","cc"};


を実行して


2次元配列aを作製し


生成される


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

a[2][0]

a[2][1]

a[2][2]



文字データ

'a'

'a'

'\0'

'b'

'b'

'\0'

'c'

'c'

'\0'

a[0][0]='a';

a[0][1]='a';

a[0][2]='\0'

a[1][0]='b';

a[1][1]='b';

a[1][2]='\0';

a[2][0]='c';

a[2][1]='c';

a[2][2]='\0';


のように格納されています


ここで


a[0][0]のアドレスを格納しているポインタ変数*aに


%s出力変換指定子を用いて


printf("%s\n", *a);


を実行したなら


aa


が表示されます


a[0][0]='a';

a[0][1]='a';

a[0][2]='\0'

a[1][0]='b';

a[1][1]='b';

a[1][2]='\0';

a[2][0]='c';

a[2][1]='c';

a[2][2]='\0';

a[0][0]='a';

a[0][1]='a';

a[0][2]='\0'


'a'

'a'

'\0'


の部分までで


1つの文字列データ


"aa"


を構成していますが


その文字列データ"aa"を格納しているメモリのアドレスが


*a


とみなされるので


printf("%s\n", *a)



実行されると


文字列

aa


コマンドプロンプト画面に表示されます」


アレサ「なるほど


そうでしたの(#^^#)


では


配列変数


a[0][0]


に格納されている文字データ'a'



コマンドプロンプト画面に表示したい場合は


どうしたらよいのですの?」



ソーラー「



配列変数


a[0][0]


のアドレスを格納しているポインタ変数が*a


なら


配列変数


a[0][0]


に格納されている文字データ'a'にアクセスするには


配列変数


a[0][0]


のアドレスを格納しているポインタ変数*a



アスタリスク演算子*を作用させた



             **a



もちいれば


             **a




配列変数


a[0][0]


にアクセスし


配列変数


a[0][0]


に格納されている文字データ'a'


をあらわすことになるね


だから


%c出力変換指定子をもちいて


printf("%c\n", **a);


を実行すれば


コマンドプロンプト画面に


a


が表示されることになります


そのプログラムはこちらです

👇


#include <stdio.h>


int main() {


char a[3][3] = { "aa","bb","cc" };


printf("%c\n", a[0][0]);

printf("%c\n", a[0][1]);

printf("%c\n", a[0][2]);

printf("%c\n", a[1][0]);

printf("%c\n", a[1][1]);

printf("%c\n", a[1][2]);

printf("%c\n", a[2][0]);

printf("%c\n", a[2][1]);

printf("%c\n", a[2][2]);


printf("%c\n", **a);//👈🌞ここです

return 0;


}


ビルド実行結果


a

a

(空白)

b

b

(空白)

(空白)

a👈🌞ここです


ソーラー「どうだったかな?


2次元配列aのaは2次元配列の配列変数の先頭の配列変数のアドレスを格納するポインタ変数のアドレスを格納するポインタ変数となります



意味がわかったかな?」


solarplexuss「う~ん まずまずいいかんじ~(^_^)/かな?」 







  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る