変数のスコープ(Scope:有効範囲)



目 次


変数のスコープ(Scope:有効範囲)と記憶域クラス

 
変数のスコープ
有効範囲意味
関数関数内全域で有効
ファイルコンパイル・翻訳単位内全域で有効
ブロックブロック内で有効
関数原型関数宣言の内部でのみ有効
 
 
記憶域クラス
記憶域クラス指定子メモリ領域変数の適応範囲
auto(自動変数):省略可動的・スタック局所(local)
static(静的変数)静的局所または大域:宣言されている場所による
extern(外部変数)静的または空大域(global)
register(レジスタ変数)レジスタまたはスタック局所(local):コンパイラの最適化等で自動適応
typedef(型定義)静的または空局所または大域:宣言されている場所による
  • 記憶領域
    • 動的記憶:変数を必要とするときだけメモリ上にある番地(スタック領域という)に変数値記憶用の領域を確保し、不要になったらそのメモリ領域を開放する。
    • 静的記憶:コンパイル時にその変数値記憶用のメモリ領域を、固定的に確保してしまう。
  • 宣言と定義
    • 宣言:変数またはパラメータの型指定
    • 定義:変数値記憶用のメモリ領域の確保

記憶領域とスコープのサンプルプログラム

  1. 静的記憶と動的記憶
    #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
    ****************************************************************/
  2. ファイル有効範囲とブロック有効範囲
    #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
    ****************************************************************/
  3. 有効範囲の入れ子
    #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
    ****************************************************************/

構造化プログラミング

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

識別子(変数、関数等)の結合(linkage)

  • 別の場所で2回以上宣言された識別子(変数、関数等)を同じものとして扱うことを結合(linkage)という。
  • ソースプログラムをいくつかのファイルに分割してコンパイルする場合、ファイルの1つ1つを翻訳単位という。他の翻訳単位で定義されたオブジェクト(変数、関数等)にアクセスしたいときは、オブジェクトの宣言時に記憶域クラス指定子 extern を用いる。
     
    結合の種類
    結合名意味備考
    外部結合翻訳単位を超えて結合他の翻訳単位へのアクセスに extern
    内部結合1つの翻訳単位の中で結合1つのファイル内でのみ有効
    無結合結合しないただ1度しか宣言されない

外部結合と内部結合のサンプルプログラム

  1. ファイル#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. ファイル#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. ファイル#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);
    }
  4. 実行結果
    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


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-05-28 (木) 12:31:50 (1547d)