ホーム » スタッフ » 斉藤徹 » 変数の寿命と有効範囲、関数と引数

2011年4月
« 3月   5月 »
 12
3456789
10111213141516
17181920212223
24252627282930

最近の投稿(電子情報)

アーカイブ

カテゴリー

変数の寿命と有効範囲、関数と引数

最初に、先週の未消化分ということで、switch – case 文を説明。 caseラベルにジャンプする概念と、break 文の必要性を解説。

大域変数・動的局所変数・静的局所変数

変数には、寿命と有効範囲という概念が重要であり、 局所変数であれば、宣言されたブロックの中でのみ有効。 大域変数は、どこからでも使える変数で便利だけど、危険な使い方。 局所変数は、一般的に動的変数であり、ブロックに入った時に作られ、 ブロックを抜けると消滅する。 しかし、static キーワードを付けた局所変数は、静的変数となり、 プログラム起動時に作られ、プログラム終了まで生き残る。

int x = 123 ;            // 静的大域変数
void foo() {
int x = 234 ;        // 動的局所変数
x++ ;
printf( "%d" , x ) ;
}
void bar() {
static int x = 345 ; // 静的局所変数
x++ ;
printf( "%d" , x ) ;
}
void baz() {
x++ ;
printf( "%d" , x ) ;
}
void main() {
foo() ;   // 235
bar() ;   // 346
baz() ;   // 124
foo() ;   // 235
bar() ;   // 347
baz() ;   // 125
}

関数と引数

関数と引数の説明として、実引数のコピーが仮引数に渡されて、局所変数の仮引数は 関数処理と同時に消滅するという解説を行う。 これにより、関数での副作用が呼び出し側に伝わらないようにすることを説明。 一方で、関数の副作用を伝えたい場合は、値渡しではなく、ポインタ渡しをすることを説明。

// 値渡し(副作用が無い)
void foo( int x ) {
x++ ;
printf( "%d" , x ) ;
}
void main() {
int x = 123 ;
foo( x ) ;  // main::x とfoo::xは別の入れ物
foo( x ) ;
}
// ポインタ渡し(ポインタ経由で副作用)
void foo( int* p ) {
(*p)++ ;
printf( "%d" , *p ) ;
}
void main() {
int x = 123 ;
foo( &x ) ;
foo( &x ) ;
}

説明において、間違い・勘違いを防ぐためのテクニックとして、 switch-caseでは、最後の行にも breakを書くとか、次のcaseになだれ込みでも、/*no break*/ コメントを入れるとかのテクニックを紹介。 大域変数では、一時的な変数と間違われないように、使用目的が分かるような長い名前をつけるとか、大域変数は単語先頭を大文字、#define 定数は名前をすべて大文字とするといったような、 誤解されないテクニックも紹介する。