char** k;により生成されるポインタのポインタ変数kにはポインタ型の配列宣言char *a[3];のaを代入でき、2次元配列aのアクセスしているメモリに2次元配列kでアクセスできるようになります

ソーラー「


ポインタ変数宣言


char *a[3];


を実行すると


3つのポインタ変数


a[0]

a[1]

a[2]


が生成されました


その時のプログラムは


こちらです

👇

#include <stdio.h>


int main() {



char *a[3] ;


a[0] = "aa";

a[1] = "bb";

a[2] = "cc";



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

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

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

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;


}


ビルド実行結果


aa

bb

cc

a

a


b

b


c

c


00FDFCC8(👈ポインタ変数a の格納しているアドレスです)


ソーラー「


char* 型の配列宣言


char* a[3] ;


により


char* 型のポインタ変数

a[0]

a[1]

a[2]

生成され


a[0] = "aa";

a[1] = "bb";

a[2] = "cc";


の実行により


メモリに


文字列データ

"aa"

"bb"

"cc"


が格納されています


このとき


ポインタ変数

a[0]

a[1]

a[2]

文字列データ

"aa"

"bb"

"cc"

を格納しているメモリの先頭のメモリのアドレスが格納され


初期化されていますね


そして


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

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

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


の実行により


aa

bb

cc


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


このとき


ポインタ変数

a[0]

a[1]

a[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';


と格納されています


👆このことは


char型のポインタ変数bに


アドレスが代入されると


配列変数


b[0]

b[1]

b[2]

を生成することができ


配列変数


b[0]

b[1]

b[2]

に文字データが代入できるのと仕組みは同じですね」


アレサ「そうですの ソーラーさん」


ソーラー「ところで


char *a[3] ;


により

ポインタ変数

a[0]

a[1]

a[2]

が生成されていますが


このときのa



             実は


        💖char**型のポインタ変数💖


であり


char型の変数のアドレスを格納するポインタ変数のアドレスを格納するポインタ変数


となっています


ビルド実行結果をみると


aはアドレス00FDFCC8を格納しているのがわかりますね



        見方を変えると



char *a[3];においては


char型の変数のアドレスを格納するポインタ変数のアドレスを格納するポインタ変数


a


が生成され


aには


アドレスが格納されているので


ポインタ変数

a[0]

a[1]

a[2]

を生成することができ


a[0] = "aa";

a[1] = "bb";

a[2] = "cc";


を実行することにより


メモリに文字列データ


"aa"

"bb"

"cc"


が格納されているとみることもできます


a



char**型のポインタ変数


なので


別の


char**型のポインタ変数宣言


char** i;


を実行した場合


生成された


char**型のポインタ変数iに


i=a;



同じchar**型のポインタ変数aを代入することができます


i=a;


を実行すると


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


iに代入されることになります


すると



          なんと

配列変数


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]


と全く等しい構造の


配列変数

i[0][0]

i[0][1]

i[0][2]

i[1][0]

i[1][1]

i[1][2]

i[2][0]

i[2][1]

i[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]

のアクセスしているメモリに


配列変数

i[0][0]

i[0][1]

i[0][2]

i[1][0]

i[1][1]

i[1][2]

i[2][0]

i[2][1]

i[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'

ですが


配列変数

i[0][0]

i[0][1]

i[0][2]

i[1][0]

i[1][1]

i[1][2]

i[2][0]

i[2][1]

i[2][2]

の格納している文字データも

'a'

'a'

'\0'

'b'

'b'

'\0'

'c'

'c'

'\0'

となります


ですので


printf("%s\n", i[0]);

printf("%s\n", i[1]);

printf("%s\n", i[2]);


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

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

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

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

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

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

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

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

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


が実行されると


ビルド実行結果


aa

bb

cc

a

a


b

b


c

c


がコマンドプロンプト画面に表示されることになります


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

👇

#include <stdio.h>


int main() {



char *a[3];


a[0] = "aa";

a[1] = "bb";

a[2] = "cc";



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

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

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


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);


char** i;


i = a;



printf("%s\n", i[0]);

printf("%s\n", i[1]);

printf("%s\n", i[2]);


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

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

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

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

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

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

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

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

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


printf("%p\n", i);



return 0;


}


ビルド実行結果


aa

bb

cc

a

a

(空白)

b

b

(空白)

c

c

(空白)

0116FED0(👈ポインタ変数a の格納しているアドレスです)


aa

bb

cc

a

a

(空白)

b

b

(空白)

c

c

(空白)

0116FED0(👈ポインタ変数i の格納しているアドレスです)


アレサ「


i = a;


が実行されたので


char**型のポインタ変数


a

i

の格納しているアドレスが


同じ


0116FED0


となっています


このように


a=i;

が実行されて


char**型のポインタ変数


a

i

の格納しているアドレスが


同じだと


配列変数


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]



配列変数

i[0][0]

i[0][1]

i[0][2]

i[1][0]

i[1][1]

i[1][2]

i[2][0]

i[2][1]

i[2][2]


アクセスするメモリはおなじになるのですね」


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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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