先週のC言語の制御構文のシメとして、switch-case文の説明をしてから、 変数の寿命とスコープの説明を行った。
switch-case文の説明では、以下の例は期待通りの動きをしない…といった例も交えて説明。 ただし、double誤差問題や文字列のポインタ関連なので、以後の授業で改めて説明が必要だろう。
// double誤差問題 double x ; for( x = 0.0 ; x <= 1.0 ; x += 0.1 ) switch( x ) { case 0.3 : printf( "A" ) ; // 0.299999...と0.3は違う値になるかも break ; } // 文字列の比較の問題 char str[ 10 ] ; scanf( "%s" , str ) ; switch( str ) { // strの先頭番地と"yes","no"の先頭番地の比較 case "yes" : printf( "はい" ) ; break ; case "no" : printf( "いいえ" ) ; break ; }
変数の寿命とスコープ
最初に、以下の様なプログラムが期待通りに動かない説明をして、 大域変数を共用することの問題を話す。
int i ; // 大域変数(global variable) void foo() { // Aを2回表示 for( i = 0 ; i < 2 ; i++ ) printf( "A" ) ; } void main() { // foo(Aを2回表示)を2回呼び出すつもり for( i = 0 ; i < 2 ; i++ ) foo() ; }
こういったトラブルを避けるためには、局所変数を使えば良い。
局所変数を使って、目的の処理…。改良版はココをクリックで表示。
最近の構造型プログラム言語であれば、 変数には寿命(変数が、作られる/消える、タイミング)と、 スコープ(変数が使える範囲)がある。
#include <stdio.h> // 静的大域変数(スコープ全体,寿命:起動から終了) int x = 123; void foo() { // 動的局所変数(スコープ:foo内部,寿命:foo呼出から戻るまで) int y = 234 ; // 静的局所変数(スコープ:foo内部,寿命:起動から終了) static int z = 345 ; x++ ; y++ ; z++ ; printf( "%d %d %d¥n" , x , y , z ) ; } void main() { foo() ; // 124,235,346が表示 foo() ; // 125,235,347が表示 }
関数の引数
関数の引数の受け渡しの説明。
返り値の型 関数名( 仮引数の宣言 ) { 何らかの処理 ; // 関数に入ると仮引数が局所変数で作られ、 return 式 ; // 実引数が代入される。 } void main() { 関数名( 実引数 ) ; // 実引数は仮引数にコピーされる。 }
値渡し、ポインタ渡しなどの説明をしたいけど、時間なので次週に説明。 残り時間では、BCPL→B言語→C言語(K&R-C→ANSI-C)→C++といった C言語の変遷を簡単に紹介。