Sponsored Link
 
>>  Main > Programing > Primary > 0012

D言語入門 第12章 - 変数のスコープ

#01 - ローカルスコープ

今回は…

変数のスコープについて説明します。
変数の寿命とかなり似ている部分ですが、違いはあります。
どのくらい違うかというと…
寿命が「時間」のようなものであるのに対し、スコープはコード内における「場所」のようなものを指します。
アクセスすることのできる場所…見える場所という意味です。

変数の寿命ではブロックを越えてアクセスしようとしたらだめだというお話をしました。
でも、実際にはポインタで無理やり参照してコンパイルも成功していました。
でも、今回のサンプルコードではコンパイルが通りません。
アクセスできる場所にあるかどうか、その辺がスコープにかかわってくるものです。
詳細は以下のサンプルコードをご覧ください。

今回のミソ

  • スコープはアクセスできる範囲のこと
  • 同じあるいはネストしたブロック内のスコープを、ローカルスコープと言う
  • ローカルスコープからのみアクセスできる変数をローカル変数(局所変数・内部変数)という

サンプルコード

int main(char[][] args)
{
    // ブロック1開始
    int a=1;
    {
        // ブロック2開始
        
        // ブロック2で変数bを宣言
        int b=0;
        
        if(a==1){
            // ブロック3開始
            
            // OK
            // ブロック1とブロック2が終わっていないのでaもbも使える。
            // ブロック3で変数cを宣言
            int c=a+b;
            
            // ブロック3終了
        }
        
        // エラー。
        // ブロック2は終わっていないのでbは使えるが、
        // ブロック3はすでに終わっているのでcという変数は使えない
        c = b+1;
        
        // ブロック2終了
    }
    
    // エラー。
    // ブロック1は終わっていないのでaは使えるが、
    // ブロック2とブロック3が終わっているので
    // bとcの変数は使えない
    a = b+c;
    
    {
        // ブロック4開始
        
        // OK
        // すでにブロック2は終わっており、
        // 再び変数 b が宣言できるようになっている。
        int b = 100;
        
        // エラー
        // すでにブロック1でaが宣言されているので、
        // もう一度aを宣言することはできない。
        int a = 400;
        
        // ブロック4終了
    }
    
    return 0;
    // ブロック1終了
}

実行結果

(コンパイルエラーを起こします。)

まとめ

このように、変数を使える範囲(スコープ)が決められているので、有効に利用するといいと思います。
たとえば、tempやhogeとかfugaなどというような一時的な作業用の変数などを使う際には "{" と "}" で囲んで変数限定してやるのがいいと思います。
ちなみに、今回やったスコープ内でのみアクセスすることのできる変数を、ローカル変数(局所変数・内部変数)と言ったりもします。
また、このようなスコープをローカルスコープと言います。
ローカルスコープはたとえば関数内で宣言された変数に対してはその関数内でしか使うことができない、というようなやつのことです。
次は、このブロック内で有効になるというスコープを無視してアクセスすることのできるグローバル変数(大域変数)というものについて説明します。

#02 - 大域変数

今回は…

グローバルスコープで宣言される変数「グローバル変数(大域変数)」について説明します。

まず、グローバルスコープについてですが、関数の外側のあたり…その中でも特に、モジュール(ファイル)の外からもアクセスすることができる範囲をグローバルスコープといいます。
このスコープを持つ変数はグローバル変数と言って、どこからでもアクセスすることのできる変数になります。
これまで扱った関数は、グローバルスコープなので、基本的にはどこからでもアクセスすることができますね。
グローバル変数のほうは、まぁ、普通、あんまり作りませんが。
ちなみに、この大域変数の寿命は、やはりプログラムが開始されてから終了するまでとなっています。
この大域変数を、寿命の観点から見て言えば外部変数と言ったりもします。

今回のミソ

  • モジュール(ファイル)を越えてもアクセスできる範囲をグローバルスコープという
  • グローバルスコープは、つまり関数や構造体の外側の部分
  • グローバルスコープの変数をグローバル変数(大域変数)という。
  • グローバルスコープの変数や関数は、面倒でなければできる限りpublicをつけるといい

サンプルコード

import std.stdio;


// グローバル変数 global_x を定義
int global_x = 10;

// グローバル変数の場合、できればpublicとつけておくとわかりやすくなる
public int global_y = 20;

int main(char[][] args)
{
    // ブロック1 開始
    
    // グローバル変数はグローバルスコープを持っているのでどこからでもアクセス可能
    writefln(global_x + 10 * global_y);
    
    // エラー
    // グローバルスコープにglobal_xがあるので、
    // この名前でローカルスコープにglobal_xという変数を作ることはできない
    int global_x;
    
    // ブロック1 終了
    return 0;
}

実行結果

(コンパイルエラーを起こします。)

まとめ

どこからでもアクセスすることのできる範囲「グローバルスコープ」と、「グローバル変数」について説明しました。
次は、そのモジュール(ファイル)内からならアクセスできるけれど、ほかのモジュール(ファイル)からはアクセスすることができないという

#03 - ファイルスコープ

今回は…

ファイルスコープについて説明します。

まず、前回のグローバルスコープですが、これにはひとつ懸念があります。
もしかしたら、自分の知らないところで勝手に値が書き換えられてしまうかもしれないというところです。
グローバルスコープはモジュール(ファイル)を越えてアクセスすることができるので、別のファイル内で値が変更されてしまうという危険性があるのです。
これを避けるために、その定義をしたモジュール(ファイル)内からしかアクセスすることのできないスコープ「ファイルスコープ」というものがあります。
グローバルスコープで変数を定義する場合にはpublicとしましたが、ファイルスコープの場合、privateとします。
ちなみに、さっきからファイル変数とか言わずにファイルスコープの変数とかいうのは、ファイル変数なんて単語は普通使わないからです。
グローバルスコープの変数は、グローバル変数。
ローカルスコープの変数は、ローカル変数。
でも、ファイルスコープの変数はファイルスコープの変数。

今回のミソ

  • モジュール(ファイル)内のどこからでもアクセスできる範囲をファイルスコープという
  • ファイルスコープの変数や関数は、つまり関数や構造体の外側の部分に記述し、さらにprivateとつける。

サンプルコード

import std.stdio;


// ファイルスコープの変数 file_x を定義
private int file_x = 10;

// ファイルスコープ変数の場合、必ず private とつける
private int file_y = 20;

int main(char[][] args)
{
    // ブロック1 開始
    
    // ファイルスコープなのでどこからでもアクセス可能
    writefln(global_x + 10 * global_y);
    
    // ブロック1 終了
    return 0;
}

実行結果

210

まとめ

というわけで、グローバルスコープのときとほとんど変わりませんが、ファイルの外部からは隠ぺいすることができているはずです。
グローバル変数よりはこっちのほうが使う機会が多いですね。
あんまり情報を駄々漏れにするのはよくありません。
複雑化してデバッグがしにくくなったり、名前が衝突したりしますから…。

#summary - まとめ

第12章のミソ

  • スコープはアクセスできる範囲のこと
  • 同じあるいはネストしたブロック内のスコープを、ローカルスコープと言う
  • ローカルスコープからのみアクセスできる変数をローカル変数(局所変数・内部変数)という
  • モジュール(ファイル)を越えてアクセスできる範囲をグローバルスコープという
  • グローバルスコープは、つまり関数や構造体の外側の部分
  • グローバルスコープの変数をグローバル変数(大域変数)という。
  • グローバルスコープの変数や関数は、面倒でなければできる限りpublicをつけるといい
  • モジュール(ファイル)内のどこからでもアクセスできる範囲をファイルスコープという
  • ファイルスコープの変数や関数は、つまり関数や構造体の外側の部分に記述し、さらにprivateとつける。

宿題

ファイルスコープとローカルスコープ、自動変数の寿命と静的変数の寿命がわかっているぜ!って「思われる」ようなプログラムを一つ組んでみましょう。

コメント

さて、今回はスコープについてやりました。
できるだけ変数の寿命とは違うイメージになるように記述しましたが…
さて、次回のD言語入門講座は…
「構造体のメンバをまとめて定義する方法(with文)」について説明していきます。
そんなわけで、宿題できたら、あるいは予想ついたら次にいきましょう~

ページトップ / 目次 / 次へ
Copyright©SHOO All rights reserved. / LastModified : 2007/12/12(水)[05:52:40]