配列システムとポインタ変数システムはとても似ています。そのことを考察してみましょう。🌞
配列システムとポインタ変数システムはとても似ています そのことを考察してみましょう。🌞
ソーラー「さあ、それでは
配列システムとポインタ変数システムがとても似ていることを
考察してみよう。」
アレサ「ついにここまできたんですの」
ソーラー「まずは
ポインタ変数をつかって
数値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[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
に代入されるときへと続くことになるんだ。」
アレサ「そうなんですか・・・惜しいですね」
ソーラー「ということで
ポインタ変数システムは
ポインタ変数システムそのものになっているとはどういうことか
考察してみよう。」
アレサ「はい???
ポインタ変数システムは
ポインタ変数システムそのものなのではないですか。」
ソーラー「ピンポ~ン アレサ正解だね」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます