ここでポインタ変数を導入してみます

メモリとアドレスと変数の関係について学んでみましょう 

こんにちは アレサです。 


午前は


現在、このカクヨムでも連載されている


プレミアム ミリオンセラー作家


佐月 詩 さん原作の


            長編映画 「ft王」



         ~そして、清らかさの意味を知る~


           

             時の涙  前編



をソーラーさん達みんなで見に行ってきました。


わくわくと感動で涙が止まりませんでしたの。


その余韻がまだ残っています。


午後からは


今日は、しとやかにメモリとアドレスのお話をしてみたいとおもいます。



アドレスとはコンピュータ内のメモリにデータを保存するときに


そのデータを格納するメモリに


もとからつけられている番号(住所)のことです。


番号(住所)がわかれば、


そこに保存されているデータを


その番号(住所)をつかって呼び出すことができるわけなんです。


いままで 


コンピュータのメモリに


変数を用いてデータを格納してきました。


変数とデータを格納するメモリにつけられているアドレスには


対応関係があります


例えば int型(4バイト)の変数aならば


変数aに格納される数値は


数値1なら


00000000 00000000 00000000 00000001

👆    👆    👆    👆

1バイト 1バイト 1バイト  1バイト


数値2147483647なら


11111111 11111111 11111111 11111111

👆    👆    👆    👆

1バイト 1バイト 1バイト  1バイト



のように


4バイトにわたって格納されることになりますが


コンピュータは


1バイトを基準としてデータを管理する仕組みとなっており


その1バイトごとにアドレスが割り当てられていますので


変数aは


例えば


0019FF54

0019FF55

0019FF56

0019FF57

のような4つのアドレスをもっていることになります


変数aのアドレス(データを格納するメモリにつけられている番号(住所))


アドレス演算子&を変数aにもちいて&aのように表記されますが


&aは


変数aが持っている4つのアドレス

0019FF54

0019FF55

0019FF56

0019FF57

のうち


先頭のアドレス0019FF54だけを表しています。


この&aが


変数aが持っている4つのアドレス

0019FF54

0019FF55

0019FF56

0019FF57

のうち


先頭のアドレス0019FF54だけを表すというシステムは


C言語のなかでいたるところで見られます。


ですので


おぼえておられるとC言語の理解がより深まることになると思われますの😊



実際にプログラムを組んで


変数aのアドレス &aがどのような数値になっているか


確かめてみましょう。



#include <stdio.h>


int main(void){

int a=1;

printf("変数aに格納された値は%dです。\n",a);

printf("変数aのアドレスは%pです。\n",&a);

/*ここで変数aのアドレス情報を知るために

変数aに

アドレス演算子&がつかわれています。

&aはコンピュータのメモリに2進数数値で格納されています。


2進数数値でメモリに格納されている

アドレス&aを16進数でprintf出力表示させるために

%p出力変換指定子がもちいられています*/

return 0;

}


コンパイル結果

EAZY IDECの場合


変数aの値は1です。

変数aのアドレスは0019FF54です。



Visual Studioの場合

ビルド実行結果


変数aの値は1です。

変数aのアドレスは00CFFC7Cです。



まず、変数宣言a、初期化a=1をおこない,


そのあと変数aのアドレスである&aをprintf出力表示しています。


統合開発環境EAZY IDECでは


変数aに数値を代入せず


初期化a=1;


をおこなわなくても


変数aのアドレスを取得することはできます。


#include <stdio.h>


int main(void){

int a;

printf("変数aの値は%dです。\n",a);

printf("変数aのアドレスは%pです。\n",&a);

return 0;

}


コンパイル結果


変数aの値は4198543です。

変数aのアドレスは0019FF54です。



Visual Studioの場合


エラー C4700 初期化されていないローカル変数 'a' が使用されます


と表示されビルドエラーになります。



変数aの初期化を行わないと


いつも通りお馴染みのモンスター数値さん


4198543が変数aに格納されていますね。


ですが、


変数aのアドレスは


(EAZY IDECの場合のみ)


変数aに格納される数値の値にかかわらず0019FF54となっています。


もうすこし試してみたいと思います


int a=5;



aに数値5を代入した場合,


変数aのアドレスはどうなっているのでしょうか?


#include <stdio.h>


int main(void){

int a=5;

printf("変数aの値は%dです。\n",a);

printf("変数aのアドレスは%pです。\n",&a);

return 0;

}


コンパイル結果

EAZY IDECの場合

変数aの値は5です。

変数aのアドレスは0019FF54です。



ビルド結果

Visual Studioの場合

変数aの値は5です。

変数aのアドレスは00EFFBDCです。



EAZY IDECの場合では

変数aのアドレスは0019FF54ですね。

変数aに格納される数値の値にかかわらず

変数aのアドレスは同じということになります。


ですが

Visual Studioの場合


変数aの値は5です。

変数aのアドレスは00EFFBDCです。



変数aに1が格納されているときのビルド結果


変数aの値は1です。

変数aのアドレスは00CFFC7Cです。


の時と


変数aのアドレスは違ってきています。


この辺りはコンパイラの仕様の違いとなっています。


EAZY IDECの場合


この変数aはint型なので4バイトの容量をもち


その連続した4バイトのうちの


先頭の1バイトのアドレスが0019FF54となっています。



それでは3つの変数a,b,cを変数宣言、初期化をおこなうと


そのアドレスはどのように表示されるでしょうか?


#include <stdio.h>


int main(void) {

int a = 5;

printf("変数aの値は%dです。\n", a);

printf("変数aのアドレスは%pです。\n", &a);


int b = 10000;

printf("変数bの値は%dです。\n", b);

printf("変数bのアドレスは%pです。\n", &b);



int c = 12;

printf("変数cの値は%dです。\n", c);

printf("変数cのアドレスは%pです。\n", &c);



return 0;

}

EAZY IDECの場合


コンパイル結果


変数aの値は5です。

変数aのアドレスは0019FF54です。

変数bの値は10000です。

変数bのアドレスは0019FF50です。

変数cの値は12です。

変数cのアドレスは0019FF4Cです。



アレサ「


3つの

変数a

変数b

変数c

を作製すると


その

変数a

変数b

変数c

に対応する3つのアドレスが存在することになります。


このときメモリ内では


0019FF54👈変数aと名づけられ管理されている4つのアドレス

0019FF53

0019FF52

0019FF51

0019FF50👈変数bと名づけられ管理されている4つのアドレス

0019FF4F

0019FF4E

0019FF4D

0019FF4C👈変数cと名づけられ管理されている4つのアドレス

0019FF4B

0019FF4A

0019FF49



仲良く


変数aの管理している4つのアドレス

変数bの管理している4つのアドレス

変数cの管理している4つのアドレス


が連続してならんでいます。


変数aよりあとに変数bを作製したのに


なぜか

変数bのアドレスの番号は

変数aのアドレスの番号よりちいさくなっています


つまり


下の図のように


新しい変数を作成するたびに


0019FF54👈変数aと名づけられ管理されている4つのアドレス

0019FF53

0019FF52

0019FF51

0019FF50👈変数bと名づけられ管理されている4つのアドレス

0019FF4F

0019FF4E

0019FF4D

0019FF4C👈変数cと名づけられ管理されている4つのアドレス

0019FF4B

0019FF4A

0019FF49


だんだん小さいアドレスのメモリが


新たに作成された変数に


割り当てられています。


この場合は


新しい変数を作成するたびに


新しい変数には


だんだん小さいアドレスのメモリが割り当てられていますが


場合によっては


これとは逆に


新しい変数を作成するたびに


0019FF4C👈変数aと名づけられ管理されている4つのアドレス

0019FF4D

0019FF4E

0019FF4F

0019FF50👈変数bと名づけられ管理されている4つのアドレス

0019FF51

0019FF52

0019FF53

0019FF54👈変数cと名づけられ管理されている4つのアドレス

0019FF55

0019FF56

0019FF57

だんだん数値の大きいアドレスのメモリが新たに作製される変数に


割り当てられることもあります。



ここでは


0019FF54👈変数aと名づけられ管理されている4つのアドレス

0019FF53

0019FF52

0019FF51

0019FF50👈変数bと名づけられ管理されている4つのアドレス

0019FF4F

0019FF4E

0019FF4D

0019FF4C👈変数cと名づけられ管理されている4つのアドレス

0019FF4B

0019FF4A

0019FF49


のように


だんだん数値の小さいアドレスのメモリが新たに作製される変数に


割り当てられているとします。


このとき


int型の変数aに格納される数値は


0019FF54👈

0019FF53👈変数aという名前で

0019FF52👈この4つのアドレスのメモリは管理されています

0019FF51👈


この4つのアドレス番号のついたメモリに格納されます。


この状態の


int型の変数aに数値1234567を格納するとしましょう。


数値1234567は2進数に変換されて


コンピュータのメモリに


2進数で


00000000‭000100101101011010000111‬(32ビット)


と格納されます


そのとき


2進数数値


00000000‭000100101101011010000111‬(32ビット)



0019FF54👈

0019FF53👈変数aという名前で

0019FF52👈この4つのアドレスのメモリは管理されています

0019FF51👈



のアドレス番号のついたメモリに


0019FF54のアドレス番号のついたメモリに10000111‬

0019FF53のアドレス番号のついたメモリに11010110

0019FF52のアドレス番号のついたメモリに‭00010010

0019FF51のアドレス番号のついたメモリに00000000


と格納されていきます


そのとき


0019FF54のアドレス番号のついたメモリに00000000

0019FF53のアドレス番号のついたメモリに‭00010010

0019FF52のアドレス番号のついたメモリに11010110

0019FF51のアドレス番号のついたメモリに10000111‬


ではなく



0019FF54のアドレス番号のついたメモリに10000111‬

0019FF53のアドレス番号のついたメモリに11010110

0019FF52のアドレス番号のついたメモリに‭00010010

0019FF51のアドレス番号のついたメモリに00000000


と格納されていきます。


つまり


2進数数値


00000000‭000100101101011010000111‬(32ビット)


の小さな位から8つずつ


0019FF54のアドレス番号のついたメモリに10000111‬

0019FF53のアドレス番号のついたメモリに11010110

0019FF52のアドレス番号のついたメモリに‭00010010

0019FF51のアドレス番号のついたメモリに00000000


格納されていきます。


次に


0019FF4C👈変数aと名づけられ管理されている4つのアドレス

0019FF4D

0019FF4E

0019FF4F

0019FF50👈変数bと名づけられ管理されている4つのアドレス

0019FF51

0019FF52

0019FF53

0019FF54👈変数cと名づけられ管理されている4つのアドレス

0019FF55

0019FF56

0019FF57

だんだん数値の大きいアドレスのメモリが新たに作製される変数に


割り当てられているとします。



この状態の


int型の変数aに数値1234567を格納するとしましょう。


数値1は2進数に変換されて


コンピュータのメモリに


2進数で


00000000‭000100101101011010000111‬(32ビット)


と格納されます


そのとき


2進数数値


00000000‭000100101101011010000111‬(32ビット)



0019FF4C👈変数aと名づけられ管理されている4つのアドレス

0019FF4D

0019FF4E

0019FF4F


のアドレス番号のついたメモリに


0019FF4Cのアドレス番号のついたメモリに10000111

0019FF4Dのアドレス番号のついたメモリに11010110

0019FF4Eのアドレス番号のついたメモリに00010010

0019FF4Fのアドレス番号のついたメモリに00000000


と格納されていきます


そのとき


0019FF4Cのアドレス番号のついたメモリに00000000

0019FF4Dのアドレス番号のついたメモリに00010010

0019FF4Eのアドレス番号のついたメモリに11010110

0019FF4Fのアドレス番号のついたメモリに10000111


ではなく



0019FF4Cのアドレス番号のついたメモリに10000111

0019FF4Dのアドレス番号のついたメモリに11010110

0019FF4Eのアドレス番号のついたメモリに00010010

0019FF4Fのアドレス番号のついたメモリに00000000


と格納されていきます。


つまり


2進数数値


00000000‭000100101101011010000111‬(32ビット)



の小さな位から8つずつ


0019FF4Cのアドレス番号のついたメモリに10000111

0019FF4Dのアドレス番号のついたメモリに11010110

0019FF4Eのアドレス番号のついたメモリに00010010

0019FF4Fのアドレス番号のついたメモリに00000000



格納されていきます。」

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

作者を応援しよう!

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

応援したユーザー

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