char (*a)[3];により生成されるポインタ変数aにはchar b[😊][3]:より生成される先頭の配列変数のアドレスを格納するポインタ変数*bのアドレスを格納するポインタ変数bを代入できます


ソーラー「


char (*a)[3];により生成されるchar (*)[3]型のポインタ変数aには


2次元配列宣言


char b[😊][3];

     👆ここが[3]になっているのがポイントです


により生成される


2次元配列b[😊][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数*bのアドレスを格納しているポインタ変数bを


             a=b;


のように


代入することができます



(😊マークには1,2,3,4,5,6・・・・などの数値を代入することができます)


たとえば


😊マークに2を代入すると


今の説明文は


char (*a)[3];により生成されるchar (*)[3]型のポインタ変数aには


2次元配列宣言


char b[2][3];

     👆ここが[3]になっているのがポイントです


により生成される


2次元配列b[2][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数*bのアドレスを格納しているポインタ変数bを

 

            a=b;


のように          


代入することができます!


となります




(⋈◍>◡<◍)。✧♡


2次元配列b[2][3]タイプの配列bのアドレスを格納しているポインタ変数は


              b


と記述する場合もありますが


先のエピソードでもみてきたように


正確には


2次元配列b[2][3]の先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数b*のアドレスを格納しているポインタ変数が


              b

となります





くわしくは後のエピソードで😊

(⋈◍>◡<◍)。✧♡



solarplexuss「


char (*a)[3];により生成されるchar (*)[3]型のポインタ変数aには


2次元配列宣言


char b[😊][3];

     👆ここが[3]になっているのがポイントです


により生成される


2次元配列b[😊][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数*bのアドレスを格納しているポインタ変数bを

 


            a=b;


のように


代入することができたとして・・・


いったい どのような使い道がこのポインタ変数に


あるのかな?」


アレサ「うぅぅ~んんん


わからないです・・・」


ソーラー「


以下の説明では


😊マークに2を代入しています


実は


aのchar (*)[3]型のポインタ変数宣言


char (*a)[3];


により生成されるchar (*)[3]型のポインタ変数aに


char型の2次元配列宣言,初期化


       char b[2][3]={"aa","bb"};


により生成される


char型の2次元配列b[2][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数*bのアドレスを格納しているポインタ変数bを


             a=b;


のように


代入すると


       2次元配列b[2][3]タイプの配列b


         と全く同じタイプの



       2次元配列a[2][3]タイプの配列a


が生成されます


       2次元配列a[2][3]タイプの配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]



を用いて


       2次元配列b[2][3]タイプの配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]



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


アクセスすることができるようになります」



solarplexuss「ど~いうことぉ?


配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

配列変数

b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

は同じメモリにアクセスする配列変数だということ?」


ソーラー「そうなんです あたり!


 2次元配列b[2][3]タイプの配列b


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

には

文字データ

'a'

'a'

'\0'

'b'

'b'

'\0'

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

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

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

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

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

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


のように代入されていますが



           a=b;



の実行により



 2次元配列a[2][3]タイプの配列a


の配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

にも

文字データ

'a'

'a'

'\0'

'b'

'b'

'\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[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

配列変数

b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

は同じメモリにアクセスする配列変数なんです」


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

👇

#include <stdio.h>


int main(void) {



char b[2][3] = { "aa","bb" };


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

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

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

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

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

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


printf("%p\n", &b[0][0]);

printf("%p\n", &b[0][1]);

printf("%p\n", &b[0][2]);

printf("%p\n", &b[1][0]);

printf("%p\n", &b[1][1]);

printf("%p\n", &b[1][2]);




char(*a)[3];


a = b;


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("%s\n", a);


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

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

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

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

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

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


return 0;


}


ビルド実行結果


a

a

(空白)

b

b

(空白)

00FAEC04

00FAEC05

00FAEC06

00FAEC07

00FAEC08

00FAEC09

a

a

(空白)

b

b

(空白)

aa

00FAEC04

00FAEC05

00FAEC06

00FAEC07

00FAEC08

00FAEC09


ソーラー「

配列変数

a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

配列変数

b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

は同じメモリにアクセスする配列変数で


文字データ


'a'

'a'

'\0'

'b'

'b'

'\0'

をあらわしているのがわかりますね」



solarplexuss「な、なんと



これって

すごいことじゃない?


char型の2次元配列bの

配列変数がアクセスしているメモリに格納されているデータに


同じタイプの


別の2次元配列aの配列変数を用いてアクセスできている!



しかも


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


の実行により


aa


まで表示されちゃって、まあ」


アレサ「うふ」


solarplexuss「


今までの知識では


bのchar型の2次元配列宣言、初期化


char b[2][3]={"aa","bb"};



aのchar型の2次元配列宣言


char a[2][3];


を実行して


         a=b;



を実行することにより


 2次元配列b[2][3]タイプの配列b


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

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

'a'

'a'

'\0'

'b'

'b'

'\0'

 2次元配列a[2][3]タイプの配列a


の配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]


に代入することはできなかった


つまり


配列bの配列変数に格納されているデータを


         a=b;



を実行することにより


別の配列aの配列変数に代入することはできなかった


それが


 2次元配列b[2][3]タイプの配列b


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

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


直接


別の配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]


を用いてアクセスできるなんて・・・」




ソーラー「そうなんです



もちろん



        char型でなくint型でも



つまり

👇


int (*a)[3];により生成されるポインタ変数aには


2次元配列宣言int b[😊][3];


により生成される


int型の2次元配列b[😊][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数b*のアドレスを格納しているポインタ変数bを


             a=b;


のように


代入することができます




たとえば


int(*a)[3];により生成されるポインタ変数aに


int型の2次元配列宣言,初期化


       int b[2][3]={{1,2,3},{4,5,6}};


により生成される


int型の2次元配列b[2][3]タイプの先頭の配列変数b[0][0]のアドレスを格納しているポインタ変数b*のアドレスを格納しているポインタ変数bを



             a=b;


のように


代入すると


       2次元配列b[2][3]タイプの配列b


         と全く同じタイプの



      2次元配列a[2][3]タイプの配列a


が生成されます


そして


このとき


 2次元配列b[2][3]タイプの配列b


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

には

数値データ

1

2

3

4

5

6

b[0][0]=1;

b[0][1]=2;

b[0][2]=3;

b[1][0]=4;

b[1][1]=5;

b[1][2]=6;


と代入されていますが



           a=b;



の実行により


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

 2次元配列b[2][3]タイプの配列b


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]

アクセスしているメモリにアクセスできるようになり


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]


数値データ

1

2

3

4

5

6

あらわすことになります


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

👇

#include <stdio.h>


int main(void) {



int b[2][3] = { { 1,2,3 },{ 4,5,6 } };


printf("%d\n", b[0][0]);

printf("%d\n", b[0][1]);

printf("%d\n", b[0][2]);

printf("%d\n", b[1][0]);

printf("%d\n", b[1][1]);

printf("%d\n", b[1][2]);


printf("%p\n", &b[0][0]);

printf("%p\n", &b[0][1]);

printf("%p\n", &b[0][2]);

printf("%p\n", &b[1][0]);

printf("%p\n", &b[1][1]);

printf("%p\n", &b[1][2]);






int(*a)[3];


a = b;


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

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

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

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

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

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


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

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

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

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

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

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



return 0;

}


ビルド実行結果


1

2

3

4

5

6

00AFF6E4

00AFF6E8

00AFF6EC

00AFF6F0

00AFF6F4

00AFF6F8

1

2

3

4

5

6

00AFF6E4

00AFF6E8

00AFF6EC

00AFF6F0

00AFF6F4

00AFF6F8



アレサ「


2次元配列b[2][3]


の配列変数


b[0][0]

b[0][1]

b[0][2]

b[1][0]

b[1][1]

b[1][2]


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]


同じアドレス番号

00AFF6E4

00AFF6E8

00AFF6EC

00AFF6F0

00AFF6F4

00AFF6F8


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

 

そして


配列変数


a[0][0]

a[0][1]

a[0][2]

a[1][0]

a[1][1]

a[1][2]

1

2

3

4

5

6

あらわすことになったのですね


🌞    🌞    🌞    🌞    🌞    🌞

 

        ここで😊おまけ😊です


🌞    🌞    🌞    🌞    🌞    🌞


int b[2][3] = { { 1,2,3 },{ 4,5,6 } };



int(*a)[3];


a = b;


の実行により


int型の2次元配列aの配列変数は


int型の2次元配列bの配列変数のアクセスしているメモリに


アクセスできるようになりましたね


このとき


int型の2次元配列bの先頭の配列変数


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


b


ではありません



int型の2次元配列bの先頭の配列変数


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


*b


です



同様に



int型の2次元配列aの先頭の配列変数


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


a


ではありません



int型の2次元配列aの先頭の配列変数


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


*a


です


ですので


int型の2次元配列aの先頭の配列変数


a[0][0]に格納されているデータは



           *a


にアスタリスク演算子を用いた



          **a



であらわされることになります 



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

👇

#include <stdio.h>


int main(void) {



int b[2][3] = { { 1,2,3 },{ 4,5,6 } };


printf("%d\n", b[0][0]);

printf("%d\n", b[0][1]);

printf("%d\n", b[0][2]);

printf("%d\n", b[1][0]);

printf("%d\n", b[1][1]);

printf("%d\n", b[1][2]);

int(*a)[3];


a = b;


printf("%d\n", a[0][0]);//👈ここです

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

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

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

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

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



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

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

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

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

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

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


return 0;

}




ビルド実行結果


1

2

3

4

5

6

1👈ここです

2

3

4

5

6

1👈ここです

2

3

4

5

6



**aを用いた



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


を実行することにより


int型の2次元配列aの先頭の配列変数


a[0][0]


に格納されている


数値データ1を表示することができましたね」

































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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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