🌞自作関数13ローカル変数のデータ情報はローカル変数が定義されたブロック内の命令文がすべて実行されるとコンピュータのメモリから消えてしまいます。そこでデータ情報維持のためにstaticが用いられます。

アレサ「みなさん


次のプログラムのように


👇プログラムはちょっと下の方にあります👇


ローカル変数aの変数宣言


int a;


を含む


void f(void){

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

}


と定義された自作関数を


main関数内で


3回


f();

f();

f();


とよびだして


実行したなら👇」


#include <stdio.h>


void f(void){

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

}


int main(void){

f();

f();

f();

return 0;

}



アレサ「👆

コンパイル結果は

どうなると おもわれますか?」


マックス「なははは


簡単、簡単 そりゃ もちろん


コンパイル結果は

1をとりこみました。

1をとりこみました。

1をとりこみました。

だろぅ」


アレサ『はい、😊そうなんです。


コンパイル結果は

1をとりこみました。

1をとりこみました。

1をとりこみました。


になります。


皆さんの予想どおりでしたか?」


マックス「超 簡単な問題だったな?



はははははははあっはははあっははははああああ



あ、あごがぁぁぁぁぁぁぁあ」



アレサ「そうですね 


このプログラムにおいては


f();をつかって


f();

f();

f();

と


自作関数

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

を3回実行するのですね


一回ごとに

f();を実行したなら


自作関数f()の中身は

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

となっているので


a++;の実行の後


aの値は2になっています。


ですが


実は


自作関数f();の実行が終わった瞬間に


ローカル変数aは数値2ごと


コンピュータのメモリから消去されています


つまりその変数名aも変数aに格納している数値も


コンピュータのメモリから消去されています


自作関数fのブロック内{}で変数宣言されたローカル変数aは


自作関数fのブロック内{}の命令文が全て実行されると


ローカル変数aに格納された値ごと消えてしまうというわけです。


ですので


次にf();

を実行するときには


自作関数の定義である

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;


が最初から実行されるので


aの値は1から始まるというわけです。


マックス「なぁああああああああにぃぃぃぃぃぃぃぃぃぃいいい


そうだったのかあ😊


f();が実行された後

a=2となっているが


そのままa=2のデータがメモリに保存されたまま


次にf();

👇

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

が実行されたとき


int a;

a=1;により

aに格納されている値が2から1に変化しているのとおもっていたぞ。」


てんC 「そうですね。


実は

f();が実行されるたびに


メモリに付けられたaという名前と


ローカル変数aに格納されている値は


コンピュータのメモリの節約のため


コンピュータのメモリから消えていたのです。


このことは


自作関数内で定義された変数には寿命があるともいわれていますが


自作関数にかぎらず


一般に


ブロック内{}で定義されたローカル変数aは


ブロック内{}の命令文が全て実行されると


aという名前の付けられたメモリはaという名前が消去され


ローカル変数aに格納されている値も


コンピュータのメモリの節約のため


コンピュータのメモリから消去されます。


そのようなわけで



        🍅自作関数f();が実行された時点で🍅


  

  🍅aという名前の付けられたメモリはaという名前が消去され🍅

   

    🍅そのメモリに格納されている値も消去されます🍅


             つまり


   🍅自作関数のブロック内で定義されたローカル変数aは🍅  


         🍅 格納している数値ともに🍅



     🍅コンピュータのメモリから消えてしまいます🍅



ですので


              自作関数の実行により


      


        自作関数内で定義された変数aに格納されている値が

              



        a=1からa=2のように変化したとしても


自作関数の実行が終了すると


             その数値データは


   ローカル変数aごとコンピュータのメモリから消えてしまいます。



             このままでは



            そのa=2のデータを


      メモリに保存したままにすることができず


         利用することができないのです



マックス 「なるほどぉ」


ぶーにゃん 「こういうことなのかにゃ?


         自作関数のブロック{}内で


    変数宣言されたローカル変数に格納された数値データは


   🍓自作関数が《1回》実行されるごとに🍓


🍓つまり自作関数のブロック{}内の命令文が実行されるごとに🍓

  

       コンピュータのメモリの節約のため


  ローカル変数の名前のデータはメモリから消えてしまうのにゃ 


     もちろんローカル変数に格納されたデータもにゃ   

  

             だから


ローカル変数宣言が行われた自作関数が実行されることにより


  ローカル変数に格納された数値データが変化していたとしても


        その数値データ情報は保持されず


         🍋きれいさっぱりと🍋


    コンピュータのメモリ内から消えてしまうのにゃ


どうかにゃ~


大事なことにゃので繰り返したのにゃ🙀」


ソーラー 「な~にぃ やっちまったな~~~😝」


アレサ「ですから


1回目の

f();を実行するとローカル変数aに格納されている数値は


自作関数の定義による

a++;により


int a=1;

より

a=1となっている状態から

a=2にとなっている状態に変化しているのですが


1回目の

f();の実行終了と同時に


ローカル変数aは


ローカル変数aに格納されている数値 a=2の情報ごと


コンピュータのメモリから消えてしまっています。


まあ そういうことにゃので


2回目の

f();の実行の際に

また最初から

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

とf();が実行されます


ですので


今のプログラムでは


コンパイル結果は

1をとりこみました。

1をとりこみました。

1をとりこみました。

となります。


大事なことにゃので繰り返しましたにゃん」


ソーラー「おおっ これは ・・・・・

 

繰り返しの3重奏  ハーモニーだね。」



アレサ 「そこで自作関数の実行とともに消えてしまう


ローカル変数aに格納されている数値データを



           🍓自作関数の実行後も🍓



         ローカル変数aに維持しつづけるには


どのようにすればよいのでしょうか?


その場合は


自作関数のブロック内で



         ローカル変数aを変数宣言するときに


        

          変数宣言int a;の前にstaticをつけ


static int a;と表記します


   そして

   

      次に           


            

            自作関数の実行により


      

     ローカル変数aに格納されている値が変化したとします



            自作関数の実行終了後 


            static を表記しない場合は


          



        ローカル変数aに格納されている値は



       ローカル変数ごと消えてしまうのですが

   


          static int a;と表記した場合は


       メモリに付けられたaという名前

       ローカル変数aに格納されている値


               ともに

       

  コンピュータのメモリから消えることはなくなります。」


ソーラー「ははあ int a;にstaticとつけることにより


          自作関数が実行されても


       メモリに付けられたaという名前

       ローカル変数aに格納されている値


が消えないようにするってわけなんだね。


staticは英語で静止したという意味がありますが


static int a;


と表記することにより


変数aは


自作関数の実行後も消えることのない


メモリに静止した(とどまる)変数となるんだね。


その様子をプログラムを組んで実際に確かめてみます🌞



👇先程のプログラム

#include <stdio.h>


void f(void){

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

}


int main(void){

f();

f();

f();

return 0;

}


コンパイル結果

1をとりこみました。

1をとりこみました。

1をとりこみました。


👆のプログラムを変更して


1回目の


f();を実行した後


a=1からa=2に変化したローカル変数aの情報を


次の2回目の


f();を実行する時にも維持しつづけるには・・・」


アレサ「はいっ(^^)


2回目のf();を実行する時にも


ローカル変数aの情報が維持されているようにするためには😊


自作関数のブロック内のaの変数宣言において


static int a;


と表記します


ローカル変数aの変数宣言の表記方法が


int a;からstatic int a;に


変更されたプログラムは次のようになります。


#include <stdio.h>


void f(void){

static int a=1; /*変更されたのはここの部分ですね*/

/*int a=1;からstatic int a=1;に変更されています*/


printf("%dをとりこみました。\n",a);

a++;

}


int main(void){

f();

f();

f();

return 0;

}


ソーラー「このプログラムをコンパイルすると・・・」


ぶーにゃん 「ぽちっ・・と」


ソーラー「


コンパイル実行してみましたら


コンパイル結果は


1をとりこみました。

2をとりこみました。

3をとりこみました。


わっでてきた。でてきた、やったね。」


アレサ「ここで


        🐥注目すべきポイント🐥は


1回目のf();が実行されたあとも


ローカル変数aは消えることなく


ローカル変数aに数値2が格納されたままとなることにあります。


         そして さらに


       🐥注目すべきポイント🐥は


この


ローカル変数aに数値2が格納されたままになるということは


       そのローカル変数aが変数宣言された


      🌞自作関数内でのみ有効である🌞


             つまり 


       🌞自作関数fを実行後🌞


             さらに


       🌞自作関数fを実行するときのみ🌞


         有効であるといえます

  


      自作関数とは別のmain関数のブロック{}内では


static int a;


により


   自作関数の実行後


  ローカル変数aに数値2が格納されたままとなっても


 そもそも


その自作関数のローカル変数aを利用できません。


これらがどのようなことを意味しているかは


これから述べていくとして


ところで次のように思われる方もいるのではないのでしょうか?


1回目の

f();

の実行された後


次に

2回目の

f();

が実行されると


すなわち

自作関数の中身


static int a=1; /*変更されたのはここの部分ですね*/

printf("%dをとりこみました。\n",a);

a++;


が実行されると


static int a=1; により


また


ローカル変数aに格納されている値は


a=1となり


そのa=1のデータをとりこんだ


printf("%dをとりこみました。\n",a);


が実行されて


1をとりこみました。


がコマンドプロンプト画面に表示されてしまうのでは?? 


このように思われるかもしれません。


ふつうはそう思われるはずです。



が


static int a=1; は 


1回目の自作関数の実行f();の時のみ有効で


2回目の自作関数の実行以降は無効


記述されていないのと同じこととなります


2回目の自作関数の実行時には


static int a=1; に関係なく


1回目の自作関数f();の実行によって


変化した自作関数内のローカル変数aに格納された値が


2回目の自作関数のローカル変数にうけつがれます。


ですので


1回目のf();


の実行で


a=1からa=2に変化したローカル変数aの格納した値は


2回目のf();


の実行時においても維持され


2回目のf();


が実行されると


static int a=1;と記述されているにもかかわらず


2をとりこみました。


がコマンドプロンプト画面に表示されます


このとき


ローカル変数aはメモリから消去されることなく


ローカル変数aに格納されている値は


2から3に変化していますが


3回目のf();


の実行時においても維持され


3回目のf();


が実行されると


static int a=1;と記述されているにもかかわらず


3をとりこみました。


がコマンドプロンプト画面に表示されます


このstatic int a=1;ように


staticがつけられた変数aを


static変数といいます。


ただし


変数宣言static int a=1;によって


保存される変数aのデータ情報は


自作関数の{}ブロック内のみとなっています。


ですから


自作関数を


f();

f();

f();


のように記述したなら


1回目の

f();が


実行されることにより1から2に変化した自作関数fのローカル変数aの格納している値は


2回目の

f();が実行される際にも


自作関数fのローカル変数aに受け継がれています。


つまりaというメモリに保存されたデータが


同様に


2回目の

f();が


実行されることにより


2から3に変化した自作関数fのローカル変数aの格納している値は


3回目の

f();が実行される際にも受け継がれることになります


ですが


ローカル変数aは自作関数のブロック{}内で変数宣言された変数なので


つまり


main関数のブロック{}内で変数宣言された変数でないため


main関数内で使用することができません。


自作関数fのローカル変数aの格納している値がstatic変数宣言により


自作関数が実行されて


自作関数内で保持され続けることになったとしても


そもそも


main関数内で使用することができないのです。


また


static int a= 1;


の部分を次のように


static int a;

a = 1;


と記述してしまうと


コンパイル結果は

1をとりこみました。

1をとりこみました。

1をとりこみました。


が表示されます。


#include <stdio.h>


void f(void) {

static int a;

a = 1;

printf("%dをとりこみました。\n", a);

a++;

}


int main(void) {

f();

f();

f();

return 0;

}


コンパイル結果は

1をとりこみました。

1をとりこみました。

1をとりこみました。


アレサ「これは


1回目のf();


が実行されると


aに格納されている値1は


a++により


aに格納されている値は2となります


static int a;


の働きにより


aに格納されている値2は


一回目の


f();


の実行の後も


メモリに保存されたままとなっています。


この状態で2回目の


f();


の実行に移ります


2回目のf();


が実行されるとき


void f(void) {

static int a;

a = 1;

printf("%dをとりこみました。\n", a);

a++;

}


static int a;


の部分は


無効となっているのですが


a = 1;


の働きにより


aに格納される値は2から1に変化します


その状態で


printf("%dをとりこみました。\n", a);


が実行されるので


2回目のf();


が実行されると


コマンドプロンプト画面には


1回目のf();


の実行の時と同じく


1をとりこみました。


が表示されます。


そして


a++;

の働きにより


aに格納されている値は


再び


1から2に変化します。


static int a;


の働きにより


aに格納されている値2は


2回目の


f();


の実行の後も


メモリに保存されたままとなっています。


この状態で3回目の


f();


の実行に移ります


3回目のf();


が実行されるとき


void f(void) {

static int a;

a = 1;

printf("%dをとりこみました。\n", a);

a++;

}


static int a;


の部分は


無効となっているのですが


a = 1;


の働きにより


aに格納される値は2から1に変化します


その状態で


printf("%dをとりこみました。\n", a);


が実行されるので


3回目のf();


が実行されると


コマンドプロンプト画面には


2回目のf();


の実行の時と同じく


1をとりこみました。


がコマンドプロンプト画面に表示されます。


そして

printf("%dをとりこみました。\n", a);


の次に実行される命令文


a++;

の働きにより


aに格納されている値は


再び


1から2に変化します。


このようなわけで


コンパイル結果


1をとりこみました。

1をとりこみました。

1をとりこみました。


がコマンドプロンプト画面に表示されることになります。


static int a;

a = 1;


でなく


static int a=1;


と表記されていなければならないのですね(^_^)/」


ソーラー「static は使い方が繊細だね。




これとは違うお話になるけど


#include <stdio.h>


int main(void){


int a=1;

printf("%d",a);


return 0;

}


コンパイル結果

1


このように


main関数が実行され


コマンドプロント画面に


コンパイル結果が表示されたときも


int a=1;のデータ情報


つまり変数aも


変数aに格納されている数値1も


コンピュータのメモリの節約のため


メモリから消えてしまってるんだ。


これでコンピュータのメモリが


データでいっぱいふさがっていて新たに


ほかのプログラムを使用できません


ということにはならなくなるよね。」



😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊😊



ソーラー「じゃじゃ~~ん😝


くりかえしま~す」


マックス「えぇっ?くりかえすのがはやってるのかぁ?」


ソーラー「


  自作関数のブロック{}内で


    変数宣言されたローカル変数に格納された数値データは


   🍓自作関数が《1回》実行されるごとに🍓


🍓つまり自作関数のブロック{}内の命令文が実行されるごとに🍓

  

       コンピュータのメモリの節約のため


     ローカル変数のデータはメモリから消えてしまうのにゃ 


     もちろんローカル変数に格納されたデータもにゃ   

  

             だから


  ローカル変数に格納された数値データが変化していたとしても


        その数値データ情報は保持されず


         🍋きれいさっぱりと🍋


    コンピュータのメモリ内から消えてしまうのにゃ


👆この文章の


コンピュータのメモリの節約のため


とはどういうことかな?」


アレサ


「先程のプログラムをもちいてコンピュータのメモリが


どのように節約されるかを一緒に考察していきます」


ソーラー「OK!~~~っ😝 アレサ」



#include <stdio.h>


void f(void){

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

}


int main(void){

f();

f();

f();

return 0;

}


このプログラムでは



まず main関数内の


先頭の

f();

が実行されます


そのとき


コンピュータは自作関数の定義


void f(void){

int a;

a=1;

printf("%dをとりこみました。\n",a);

a++;

}


を参照しています。


1番目のf();が実行されると


aの値はa++;によりa=2になっています。


ですが


f();の終了と同時に


a=2のデータはコンピュータのメモリから消えてしまいます


もし このままa=2の情報をコンピュータのメモリに記憶したなら


2回目のf();にそのデータは受け継がれるのですが


その場合


a=2のデータを


コンピュータのメモリに記憶しつづけている必要があります


コンピュータのメモリとは 


計算のため短期的にデータを保持する部分なのですが


データを保持するには上限があります。


メモリがデータで いっぱいになると 計算ができなくなります。


そこで そのような事態をさけるため メモリの容量を確保するために


メモリに格納されているa=2のデータを


ローカル変数aごと


f();の実行が終了するごとに


コンピュータのメモリから削除するというわけです。


もしかしたら


メモリ容量の少なかった昔のコンピュータにとって 


a=2のデータを メモリに保持しつづけるのは


大変だったのかもしれないのです ね」






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

作者を応援しよう!

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

応援したユーザー

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