情報処理Ⅱ 第7回:2003年12月2日(火) 問題(授業がつまらない人のために) ぷよ連結問題 前提: フィールドを2次元 配列で定義し,各マスの 「ぷよ」をint型の値で表現 する. ある地点を入力に取り,そ れと連結する「ぷよ」の個 数を求めよ. 消去できる「ぷよ」(N個以上 連結するぷよと,それに隣接する特 殊なぷよ)のマスを求めよ. : ぷよ : 特殊なぷよ 本日のテーマ: 関数と変数 目的 関数を自分で定義し,変数の利用方法・範囲を明示的に制 限することで,適切な機能分割(モジュール化,再利用) を図る. してはいけないこと main関数のみで100行以上のプログラム グローバル変数を駆使するプログラム 関数(Function) 関数の分類 自作関数: 自分で定義する.⇒ 本日のテーマ 標準ライブラリ関数: ANSIで定義されている.printfなど. POSIX準拠関数: オペレーティングシステムのインタ フェースや環境を規定した関数ライブラリ.openなど. その他のライブラリ関数: OpenGLの glutCreateWindow など. ANSI: American National Standards Institute POSIX: Portable Operating System Interface for UNIX 関数定義の方法 構文: 型名 関数名(引数並び) {文...} 型名は,関数の戻り値の型.値を返さないときは,何も書 かないか,voidと書く. 引数並びは,0個以上の「型名 変数名」をカンマで挟んだ もの.引数がないときは,何も書かないか,voidと書く. 例: double my_atof(const char *str0) {…} 例: void procedure(char *p, int x, int y) {…} 変数が[ ]を伴っていれば,それはポインタと同じ. 例: int main(int argc, char *argv[ ]) {…} は int main(int argc, char **argv) {…} と書いても同じ. 引数の授受(1) double f(double x) {return x+1;} ... b=f(a); としたとき x を関数 f の仮引数(formal argument),aを実引数(actual argument)と言う.これらを区別する必要のないときは, ともに引数(argument)という. x = a; の代入を行ってから,関数本文の処理に入る.関数 の処理が終われば,変数 x (のオブジェクト)は消滅する. 関数処理中に return 値; があれば,そこで関数の処理を 終え,値を戻り値(return value)とする. void型の関数処理中に return; があれば,そこで関数の 処理を終える.戻り値なし. 暗黙の型変換は,仮引数への代入時と,戻り値オブジェ クトの生成時に起こり得る. 値の前後にカッコは不要. 引数の授受(2) Cの関数呼び出しでは必ず値渡し(call by value)になる. 値渡し: 実引数のコピーが仮引数に格納される.その後, 仮引数の値を変更しても,実引数の値には影響しない. 参照渡し(call by reference)をしたければ,ポインタを引 数とすればよい. 参照渡し: 仮引数は,実引数の別名となる.その後,仮引 数の値を変更すれば,実引数の値もそれに変わる. Cではこの意味での参照渡しをすることができない. 関数定義の順番 呼び出す関数は,呼び出す前に(プログラムファイルの 上のほうで)宣言されていなければならない. 宣言や定義がない場合は,int 関数名( ); とみなして呼び 出しを試みる. 対策 呼び出す順序に注意して関数を並べる. 関数プロトタイプを使用する. 関数プロトタイプ (Function prototype) 「関数原型」ともいう. 構文: 型名 関数名(引数の型の並び); 「引数の型の並び」は,「引数(型と変数)の並び」でも よい.このとき仮引数名は無視される. セミコロンは必須. 例: double my_atof(const char *); 関数プロトタイプのリストを作り,その次に関数定義を 並べれば,関数定義の順番を気にすることなくプログラ ムを記述できる. main関数の型 main関数の(戻り値の)型は,int とする.void main(...) と する本も多いが,規格上適切ではない. 正常終了は return 0; と書き, 異常終了は return 1; と書くのが一般的. main関数の中以外でプログラムの実行を終えたいときは exit(0); exit(EXIT_SUCCESS); exit(EXIT_FAILURE); のいずれかを書く.(要 #include <stdlib.h>) 変数(Variable) 学ぶこと 型以外の属性(記憶域クラス,型修飾子) 有効範囲 用語説明 識別子(Identifier): 変数名,関数名,型定義名などの「名 前」 すでに宣言・定義された識別子で新たに宣言・定義しよう とすると,コンパイルエラー. オブジェクトと識別子の違い 識別子は,プログラム(静的)で記述する「ラベル」 オブジェクトは,プログラム実行中(動的)に生成される 「実体」 同一の識別子に対して複数のオブジェクトが生成されるこ ともある. 型の属性 記憶域クラス 型修飾子 extern, static, auto, register const, volatile 例: extern void function1(const char *); int x(void) {static int c=0; ...} 記憶域クラス(1) extern: 他の場所で宣言された識別子を参照する. static: そのオブジェクトの生存期間は静的記憶域期間で ある. auto: そのオブジェクトの生存期間は自動記憶域期間で ある. externとstaticは,関数に対しても指定できる.ただし staticの意味は異なる. 記憶域クラス(2) 静的記憶域期間 (static変数) static を指定した場合や,なくてもグローバル区間(ブロックの ないところ)で定義した変数が該当する. プログラムの実行に先立ち,一度だけ初期値が設定される. 初期値を指定しないオブジェクトには 0 が代入される. 初期値は,コンパイル時に計算可能な定数式でなければならな い. 自動記憶域期間 (auto変数) auto を指定した場合や,なくてもブロック内で定義した変数, 関数の仮引数が該当する. オブジェクトの定義の時点で,毎回初期化される. 初期値を指定しないオブジェクトの初期値は不定. 初期値は任意の計算式でよい. 型修飾子 const: その識別子の値はプログラムによって変更できな い.参照は可能. volatile: 処理系が知らないうちに値を変える可能性があ る.参照は可能. *p は左辺値 constの使用例: にできない int function(char *p){ } int function(const char *p){ } int function(char * const p){ } int function(const char * const p){ } p は左辺値 にできない 変数の有効範囲(1) 各変数は,定義された位置や記憶域クラスの指定により, 有効範囲(scope)を持つ. グローバル区間で定義された変数…ファイル末尾まで . ブロックの中で定義された変数…ブロック終了まで . ブロックを終えると,auto変数のオブジェクトは破棄され, static変数のオブジェクトは保存される. 変数の有効範囲(2) 変数の有効範囲とオブジェクトの生存期間 各変数に結び付けられたオブジェクトは,指定された記憶 域クラスに応じて生成・破棄される. 破棄されるまでは,スコープの外からでも(ポインタなど で間接的に)オブジェクトの参照ができる. 関数内のauto変数は,関数処理のたびに生成される. ⇒ 再帰関数が構成できる. まとめ 関数を自分で定義することができる.関数を呼び出すと き,引数は値渡しで授受される. それまでに定義した関数しか呼び出すことができない (と考えるのがよい)ので,関数定義の順番に注意する か,関数プロトタイプを利用する. 変数には,型とは別の属性として,記憶域クラスと型修 飾子を指定できる.static変数とauto変数とでは,大き く挙動が異なる. 変数の定義とオブジェクトの生成は別. オブジェクトの生成・破棄のタイミングに注意する. 発展的な話題(1) 古い関数定義の構文(K&R): 型名 関数名(引数名並び) 「引数の型と引数名;」の並び {文...} 例: int main(argc, argv) int argc; char *argv[ ]; {…} 比較:現在の構文(ANSI) int main(int argc, char *argv[ ]) {…} 発展的な話題(2) void型 関数の(戻り値の)型や引数として記述可能. void型の関数の式を値として利用できない(コンパイルエ ラー). void f(void) {…} としたとき, f(); はOK.printf("%d", f())はNG. void型の変数は定義できない(コンパイルエラー). void *型の変数は定義可能.この型は,ポインタ間の変換 などで用いられる. レポート課題 課題:「バージョン」について バージョン管理されたソフトウェアを一つ取り上げながら, バージョンの必要性・有用性をA4用紙2枚で論述する. 適切に引用し,友人などの協力があれば謝辞をつける. 提出方法:12月16日(2週間後)の授業開始時に回 収する.
© Copyright 2025 ExpyDoc