RIGHT:[[ProgI]]
&br;
&br;
CENTER:&size(28){変数のスコープ(Scope:有効範囲)};
&br;
&br;
&br;
RIGHT:谷口祐治(taniguchi@cc.u-ryukyu.ac.jp)
----
''目 次''
#contents
----
*変数のスコープ(Scope:有効範囲)と記憶域クラス [#sfe350bd]
#br
|変数のスコープ|h
|有効範囲|意味|
|関数|関数内全域で有効|
|ファイル|コンパイル・翻訳単位内全域で有効|
|ブロック|ブロック内で有効|
|関数原型|関数宣言の内部でのみ有効|
#br
#br
|記憶域クラス|h
|記憶域クラス指定子|メモリ領域|変数の適応範囲|
|auto(自動変数):省略可|動的・スタック|局所(local)|
|static(静的変数)|静的|局所または大域:宣言されている場所による|
|extern(外部変数)|静的または空|大域(global)|
|register(レジスタ変数)|レジスタまたはスタック|局所(local):コンパイラの最適化等で自動適応|
|typedef(型定義)|静的または空|局所または大域:宣言されている場所による|

-記憶領域
--動的記憶:変数を必要とするときだけメモリ上にある番地(スタック領域という)に変数値記憶用の領域を確保し、不要になったらそのメモリ領域を開放する。
--静的記憶:コンパイル時にその変数値記憶用のメモリ領域を、固定的に確保してしまう。
-宣言と定義
--宣言:変数またはパラメータの型指定
--定義:変数値記憶用のメモリ領域の確保

**記憶領域とスコープのサンプルプログラム [#r253386d]
+静的記憶と動的記憶
 #include <stdio.h>
 
 int   en = 10;      /* File Scope */
 void  inc_n(void);
 
 main(){
   printf("befor function           en=%2d\n\n",en);
   inc_n();
   inc_n();
   inc_n();
   printf("after function           en=%2d\n\n",en);
 }
 
 void inc_n(void){
   static  int sn = 0;  /* Block Scope */
   auto    int an = 0;  /* Block Scope */
   extern  int en;      /* File Scope  */
 
   printf("befor n++  sn=%2d  an=%2d  en=%2d\n",sn,an,en);
   sn++;
   an++;
   en++;
   printf("after n++  sn=%2d  an=%2d  en=%2d\n\n",sn,an,en);
 }
 
 /******************************************************* 実行結果
 befor function           en=10
 
 befor n++  sn= 0  an= 0  en=10
 after n++  sn= 1  an= 1  en=11
 
 befor n++  sn= 1  an= 0  en=11
 after n++  sn= 2  an= 1  en=12
 
 befor n++  sn= 2  an= 0  en=12
 after n++  sn= 3  an= 1  en=13
 
 after function           en=13
 ****************************************************************/
+ファイル有効範囲とブロック有効範囲
 #include <stdio.h>
 
 int   fn = 0;       /* File Scope */
 void  inc_n(void);
 void  dec_n(void);
 
 main(){
   printf("befor function            fn=%2d\n\n",fn);
   inc_n();
   dec_n();
   dec_n();
   inc_n();
   printf("after function            fn=%2d\n\n",fn);
 }
 
 void inc_n(void){
   static  int bn = 0;    /* Block Scope */
 
   printf("  befor n++        bn=%2d  fn=%2d\n",bn,fn);
   bn++;
   fn++;
   printf("  after n++        bn=%2d  fn=%2d\n\n",bn,fn);
 }
 
 void dec_n(void){
   static  int bn = 0;    /* Block Scope */
 
   printf("  befor n--        bn=%2d  fn=%2d\n",bn,fn);
   bn--;
   fn--;
   printf("  after n--        bn=%2d  fn=%2d\n\n",bn,fn);
 }
 
 /******************************************************* 実行結果
 befor function            fn= 0
 
   befor n++        bn= 0  fn= 0
   after n++        bn= 1  fn= 1
 
   befor n--        bn= 0  fn= 1
   after n--        bn=-1  fn= 0
 
   befor n--        bn=-1  fn= 0
   after n--        bn=-2  fn=-1
 
   befor n++        bn= 1  fn=-1
   after n++        bn= 2  fn= 0
 
 after function            fn= 0
 ****************************************************************/
+有効範囲の入れ子
 #include <stdio.h>
 
 int   n = 0;
 void  inc_n(void);
 
 main(){
   printf("befor function            n=%2d\n\n",n);
   inc_n();
   printf("after function            n=%2d\n",n);
 }
 
 void inc_n(void){
   static  int n = 10;
 
   printf("  befor n++               n=%2d\n",n);
   {
     int  n=20;
     printf("        in block          n=%2d\n",n);
   }
   n++;
   printf("  after n++               n=%2d\n\n",n);
 }
 
 /******************************************************* 実行結果
 befor function            n= 0
 
   befor n++               n=10
         in block          n=20
   after n++               n=11
 
 after function            n= 0
 ****************************************************************/

*構造化プログラミング [#q7d293a3]
+3つの基本処理
++順次処理:上から下へ記述された順に処理を実行する。
++選択・判断処理:条件により実行する処理を選択する。
++反復・繰り返し処理:処理を繰り返して実行する。
+モジュール化:複雑なプログラムを設計するとき、まとまって意味のある処理機能ごとにプログラムを分割し、モジュール化を行う。
++処理のまとまりを的確に把握する。
++各モジュールはできるだけ独立したものにする。
++各モジュールはできるだけ汎用性の高いものにする。
++1つのモジュールは全体を見渡せる大きさにする。

*識別子(変数、関数等)の結合(linkage) [#j1d13559]
-別の場所で2回以上宣言された識別子(変数、関数等)を同じものとして扱うことを結合(linkage)という。
-ソースプログラムをいくつかのファイルに分割してコンパイルする場合、ファイルの1つ1つを''翻訳単位''という。他の翻訳単位で定義されたオブジェクト(変数、関数等)にアクセスしたいときは、オブジェクトの宣言時に記憶域クラス指定子 extern を用いる。
#br
|結合の種類|h
|結合名|意味|備考|
|外部結合|翻訳単位を超えて結合|他の翻訳単位へのアクセスに extern|
|内部結合|1つの翻訳単位の中で結合|1つのファイル内でのみ有効|
|無結合|結合しない|ただ1度しか宣言されない|
**外部結合と内部結合のサンプルプログラム [#df41f2ba]
+ファイル#1
 #include <stdio.h>
 
 int   en = 10;
 void  inc_n(void);
 void  dec_n(void);
 
 main(){
   printf("befor function      en=%2d\n\n",en);
   inc_n();
   printf("\n");
   dec_n();
   printf("\n");
   inc_n();
   printf("\n");
   printf("after function      en=%2d\n",en);
 
   return(0);
 }
+ファイル#2
 #include <stdio.h>
 
 extern int en;
 
 void dec_n(void){
   printf(" in dec_n function  en=%2d\n",en);
   en--;
   printf(" in dec_n function  en=%2d\n",en);
 }
+ファイル#3
 #include <stdio.h>
 
 static int en=20;
 
 void inc_n(void){
   printf(" in inc_n function         en=%2d\n",en);
   en++;
   printf(" in inc_n function         en=%2d\n",en);
 }
+実行結果
 befor function      en=10
 
  in inc_n function         en=20
  in inc_n function         en=21
 
  in dec_n function  en=10
  in dec_n function  en= 9
 
  in inc_n function         en=21
  in inc_n function         en=22
 
 after function      en= 9
*Report#4 [#zd0df279]
 次のプログラムは外部変数に定義され、初期化された10個のint型データの平均を求め、各データと平均との差を表示するプログラムである。&br;
 このプログラムを以下のような関数の翻訳単位にファイルを分け、同様な動作をするプログラムを作成せよ。
|型|関数名|引数・パラメータ|機能|戻り値|
|float|get_ave|なし|平均値を求め表示|平均値|
|void|print_data|配列の添字、平均値|1つのデータと平均値との差を求め表示|なし|
+プログラム
 /*
   program   : average.c
   comments  : 結合(linkage)を用いて、平均・差を求める。
 */
 
 #include <stdio.h>
 
 int score[10]={3,5,8,9,10,6,7,9,8,3};
 
 int main(){
   int   i;
   float ave = 0.0, dif;
 
   for(i=0; i<10; i++) ave = ave + (float)score[i];
   ave = ave / 10.0;
   printf("ave = %3.1f\n",ave);
   
   for(i=0; i<10; i++){
     dif = score[i] - ave;
     printf("score[%02d]=%2d  Difference from average = %4.1f\n",i,score[i],dif);
   }
   
   return(0);
 }
+実行結果
 ave = 6.8
 score[00]= 3  Difference from average = -3.8
 score[01]= 5  Difference from average = -1.8
 score[02]= 8  Difference from average =  1.2
 score[03]= 9  Difference from average =  2.2
 score[04]=10  Difference from average =  3.2
 score[05]= 6  Difference from average = -0.8
 score[06]= 7  Difference from average =  0.2
 score[07]= 9  Difference from average =  2.2
 score[08]= 8  Difference from average =  1.2
 score[09]= 3  Difference from average = -3.8

**考察事項 [#mbd1f05d]
-変数のスコープと記憶域クラスについて考察せよ。
-コンパイルは先週のmakeコマンドを用い、Makefileとともに実行可能ファイルが作成されるまでの実行結果を示すこと。
-同様な動作をするオリジナルのプログラムを作成してまとめてもよい。例)平均からの差でA,B,C,F等の評価の表示等
----


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS