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

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

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


配列システムとポインタ変数システムがとても似ていることを


考察してみよう。」


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


ソーラー「まずは


ポインタ変数をつかって


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



#include <stdio.h>


int main(void) {


int a;

int* pta;

pta = &a;

*pta = 1;


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

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

return 0;

}



コンパイル結果


EAZY IDECの場合


1

0019FF54


Visual Studioの場合


1

00AFFDB4


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


まずaのint型の変数宣言


int a;


により


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


__________________________


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


の実行結果は


(Visual Studioの場合)

00AFFDB4となっています


ptaには変数aのアドレス&aが代入されているので


変数aのアドレス&aは00AFFDB4ですね



アドレス

00AFFDB4から始まる


00AFFDB4

00AFFDB5

00AFFDB6

00AFFDB7

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


変数aによって管理されていると仮定します



アドレス

00AFFDB4から始まる


00AFFDB3

00AFFDB2

00AFFDB1

00AFFDB0

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


変数aによって管理されている場合もあります




次に


int* pta;


により

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


こうして作成された

ポインタ変数

ptaに

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




*ptaは変数aのアドレスのメモリにアクセスすることになります



そして


*ptaを用いて


ポインタ変数ptaに格納された変数aのアドレス番号のついたメモリに数値データを格納することができます


*pta = 1;


により

ポインタ変数ptaに格納された変数aのアドレス番号の付いたメモリに1が代入されると


00AFFDB4(8ビット)

00AFFDB5(8ビット)

00AFFDB6(8ビット)

00AFFDB7(8ビット)

の4つのメモリには


00000001

00000000

00000000

00000000


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


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




さらに


*pta=5;


と記述して


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


ポインタ変数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]


が作製されています。


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


の実行結果が


010FFAF0


となっています


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


hairetu[0]のアドレスは


010FFAF0


となっています


このとき

(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のアドレスを格納しているポインタ変数hairetuに


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


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


だけど


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


ポインタ変数

hairetuが


自作関数の引数に用いられている場合


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


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


ポインタ変数

newhairetuを


hairetu =newhairetu;


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


だからこのお話の続きは


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


ポインタ変数

hairetuが


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


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


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


ポインタ変数

newhairetuが


自作関数の引数となっている


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


ポインタ変数hairetu


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


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


ソーラー「ということで


ポインタ変数システムは 


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


考察してみよう。」


アレサ「はい???


ポインタ変数システムは 


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


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


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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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