配列システムはポインタ変数システムによって構成されています。そのことを考察してみましょう。🌞

配列システムはポインタ変数システムそのものとなっていることを考察してみましょう。🌞

ソーラー「さあ、それでは


配列システムは 


ポインタ変数システムそのものになっているとはどういうことか


考察してみよう。」


アレサ「ついにここまできたんですの」


ソーラー「まずは


ポインタ変数をつかって


数値1をメモリに格納するシステムについて観察してみよう😊」



#include <stdio.h>


int main(void) {


int a;

a = 1;


int *pta;

pta = &a;


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

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

return 0;

}


コンパイル結果


EAZY IDECの場合

1

0019FF54


Visual Studioの場合


1

00AFFDB4


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


まず変数宣言


int a;


により


変数aが作製されています。


このとき

(Visual Studioの場合)


アドレス

00AFFDB4から始まる


00AFFDB4

00AFFDB5

00AFFDB6

00AFFDB7

の合計32ビットの4つのメモリは


変数aによって管理されることになります。


次に


a=1;

により

変数aに1が代入されると


00AFFDB4(8ビット)

00AFFDB5(8ビット)

00AFFDB6(8ビット)

00AFFDB7(8ビット)

4つのメモリには


00000001

00000000

00000000

00000000


とデータが格納されます。


メモリにうまく数値データ1が格納出来たね。


次に

int *pta;


により

ptaのポインタ変数宣言がおこなわれていますね。


こうして作成された

ポインタ変数

ptaに

変数aのアドレス&aが代入されると




*ptaは変数aのアドレスに格納されている数値データ1を




表すことになります。


つまり


*ptaは変数aのアドレス番号の付いたメモリにアクセスして


そのメモリに格納されている数値1をあらわすことになったわけです。


さらに


*pta=5;


と記述して


*ptaに別の数値を代入することにより


変数aのアドレス番号の付いたメモリにアクセスして


そのメモリに格納されている数値1を


別の数値5に変更することもできます。


*ptaという数値データを格納できる変数は


変数aのアドレスの付いたメモリにアクセスする窓口


となっているわけです


ですので


メモリ上に


変数a

とは

別の

変数*ptaが作製されて


変数aに数値1が格納されているメモリとは


別に


変数*ptaと名前の付けられたメモリに


数値1が格納されているわけではありません」


アレサ「なるほど・・ そうだったんですね」


ソーラー「次に


配列を使って


数値1をメモリに格納するシステムについて観察してみよっかな😊」


#include <stdio.h>


int main(void) {


int hairetu[1];

hairetu[0]=1;


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

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

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

return 0;

}


コンパイル結果


EAZY IDECの場合


1

1

0019FF54



Visual Studioの場合


1

1

010FFAF0


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


まず


配列宣言


int hairetu[1];


により

配列変数

hairetu[0]


が作製されています。


このとき

(Visual Studioの場合)

アドレス

010FFAF0から始まる


010FFAF0(8ビット)

010FFAF1(8ビット)

010FFAF2(8ビット)

010FFAF3(8ビット)

合計32ビットの4つのメモリは


配列変数hairetu[0]によって管理されることになります。



配列変数hairetu[0]は

010FFAF0(8ビット)

010FFAF1(8ビット)

010FFAF2(8ビット)

010FFAF3(8ビット)

合計32ビットの4つのメモリにアクセスしているというわけです


ですが


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


010FFAF0(8ビット)

010FFAF1(8ビット)

010FFAF2(8ビット)

010FFAF3(8ビット)

合計32ビットの4つのメモリに


配列変数hairetu[0]と名前がつけられているわけではありません。


次に


hairetu[0]=1;



により

窓口である

配列変数hairetu[0]をとおして数値データ1がメモリに格納されると


010FFAF0(8ビット)

010FFAF1(8ビット)

010FFAF2(8ビット)

010FFAF3(8ビット)

4つのメモリには


00000001

00000000

00000000

00000000


とデータが格納されます。


メモリにうまくデータが格納出来たね。」


アレサ「はいっ😊


メモリにうまくデータが格納できていますの。」


ソーラー「このとき


配列宣言


int hairetu[1];


により


配列変数

hairetu[0]

だけでなく


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


hairetu


も作製されていましたね。


こうして作製された


ポインタ変数

hairetuは


窓口である

配列変数hairetu[0]のアクセスしているメモリのアドレスを格納しているので


*hairetuは


配列変数hairetu[0]のアクセスしているメモリに


格納されている数値データ1を


表すことになります。


つまり


*hairetuは


配列変数hairetu[0]のアクセスしているメモリにアクセスして


そこに格納されている数値1をあらわすことになったわけです。


さらに


*hairetu=5;


と記述して


*hairetuに別の数値を代入することにより


配列変数hairetu[0]のアクセスしているメモリにアクセスして


そのメモリに格納されている数値1を


別の数値5に変更することもできます。


ですから


*hairetuという数値データを代入できる変数も


配列変数hairetu[0]と同様に


配列変数hairetu[0]のアクセスしているメモリにアクセスする窓口


となっているわけです


ですので


*hairetuはメモリにアクセスする窓口というだけで


メモリ上に


変数*hairetuが作製されて


配列変数hairetu[0]によってアクセスされている数値1が格納されているメモリとは


別に


変数*hairetuによって数値1が格納されているメモリが


あるわけではありません。」


ソーラー「ここでのポイントは



ポインタ変数

hairetuは


配列変数hairetu[0]のアクセスしているメモリのアドレスを格納している


ので


*hairetuは


配列変数hairetu[0]のアクセスしているメモリに格納されている

数値データ1を


表すことになる


というところなんだよ。



ここで


もう1度プログラムを観察すると


#include <stdio.h>


int main(void) {


int hairetu[1];

hairetu[0]=1;


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

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

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

return 0;

}


コンパイル結果


Visual Studioの場合


1

1

010FFAF0


ソーラー「


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

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


がともに数値データ1を表示していることに注目してください。


そもそも

配列変数hairetu[0]

ポインタ変数hairetu

はどのような関係があるのでしょうか?


実は



          配列変数hairetu[0]は


           ポインタ変数🍓🍓🍓

            hairetu🍓🍓🍓

       に格納されたアドレスにあるメモリ🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓


にアクセスする窓で


ポインタ変数

            hairetu

       に格納されたアドレスにあるメモリ


に格納された数値を表すように設定されています。




今までのエピソードでみてきたように


           *hairetuも


ポインタ変数

            hairetu

       に格納されたアドレスにあるメモリ


にアクセスする窓で


ポインタ変数

            hairetu

       に格納されたアドレスにあるメモリ


に格納された数値を表すように設定されています。


ですので


hairetu[0]と*hairetuは同じく


ポインタ変数

            hairetu

  

      に格納されたアドレスにあるメモリ


に格納された数値を表すように設定されていて


まったく等しいものをあらわしているんです。


もう驚きの展開だね」


アレサ「そうだったんですの・・」


ソーラー「だから


配列変数hairetu[0]はまんま*hairetuを


あらわしており


配列のシステムとはポインタ変数のシステムだったというわけなんだね。」



ソーラー「

配列変数hairetu[0]は


           ポインタ変数

            hairetu

       に格納されたアドレスにあるメモリ


にアクセスする窓で


ポインタ変数

            hairetu

       に格納されたアドレスにあるメモリ


に格納された数値を表すように設定されているので



ポインタ変数hairetuに


別のメモリのアドレスが格納されている


ポインタ変数newhairetu


が代入されると


配列変数hairetu[0]は


       ポインタ変数hairetuに代入された

  


       ポインタ変数newhairetu



       に格納されたアドレスにあるメモリ


にアクセスする窓となり


ポインタ変数

            newhairetu

       に格納されたアドレスにあるメモリ


に格納された数値を表すようになるんだよ。


その様子を


プログラムを構成して確認してみたいところだけど・・・」





#include <stdio.h>


int main(void) {


int hairetu[1];

hairetu[0] = 1;


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

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

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



int newhairetu[1];

newhairetu[0] = 2;


hairetu =newhairetu;

/*配列変数newhairetu[0]のメモリのアドレスを

格納しているポインタ変数newhairetuを

をポインタ変数hairetuに代入しました。*/


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

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

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

return 0;

}



コンパイル結果


EAZY IDECの場合


ファイル「C:/Users/solarplexuss/AppData/Local/EasyIDEC/project/hhhhhhhh/main.c」の

「16行目」で記述エラーを発見しました。

「lvalue」を付け忘れています。



Visual Studioの場合



E0137 式は変更可能な左辺値である必要があります

C3863 配列型 'int [1]' を割り当てることはできません。


アレサ「このプログラムでは


配列hairetuのアドレスを格納しているポインタ変数hairetuに


別の配列newhairetuのアドレスが格納されている


ポインタ変数newhairetuが代入されることにより


配列変数hairetu[0]が


ポインタ変数hairetuに代入された

ポインタ変数newhairetu

に格納されたアドレスにあるメモリ


にアクセスする窓となり


配列変数hairetu[0]が数値1を表している状態から


ポインタ変数

            newhairetu

       に格納されたアドレスにあるメモリ


に格納された数値2にかわることをしめそうとしているんですの💖


ですが・・・」



ソーラー「だけど


このようにコンパイルエラーが出るんだ。


普通は


配列のアドレスを格納しているポインタ変数hairetuに


別の配列のアドレスを格納しているポインタ変数newhairetuを


代入することはできないんだ。


だけど


配列hairetuのアドレスを格納している


ポインタ変数

hairetuが


自作関数の引数になっている場合


main関数内で配列宣言され作製された


配列newhairetuのアドレスを格納している


ポインタ変数

newhairetuを


hairetu =newhairetu;


のように代入することは可能なんだよ


だから続きは


配列hairetuのアドレスを格納している


ポインタ変数

hairetuが


自作関数の引数になっていて


main関数内で配列宣言され作製された


配列newhairetuのアドレスを格納している


ポインタ変数

newhairetuが


自作関数内で配列宣言され作製された


配列hairetuのアドレスを格納している


ポインタ変数hairetu


に代入されるときのお話のときに続くことになるんだ。」


アレサ「そうなんですか・・・惜しいですね」


ソーラー「ということで


ポインタ変数システムは 


ポインタ変数システムそのものになっているとはどういうことか


考察してみよう。」


アレサ「はい???


ポインタ変数システムは 


ポインタ変数システムそのものなのではないですか。」


ソーラー「ピンポ~ン アレサ正解だね」


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

作者を応援しよう!

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

応援したユーザー

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