- 2012-05-07 (Mon) 19:58
- プログラミング
ISO/IEC 9899 のC99の仕様とか C11のドラフト の 6.9.1 Function definitions には次のように書かれている.つまりは return なしで関数の最後まで行き,その関数の戻り値が使われたなら,何が起こるかわからないと.
12 If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
が, どうせ return 文が無いだけならコンパイラが %eax にデータを上書きしないだけなので,それを期待すれば下の階乗のプログラムは想定通りに動く(gcc 4.5.3 @ cygwin で確認).つまり,関数の最後で関数を呼び,末端の呼び出しの return をいちばん外側まで到達させる(末尾再帰なわけだけど).実際にアセンブリで見てもそうなってる.
#include <stdio.h> int fact(int k) { static int f=1; if( k <= 0 ) return f; f*=k--; fact(k); } int main(int argc, char*argv[]) { printf("%d\n", fact(10)); }
で,お手伝いしているプログラミング演習で結構な数の学生らが上のようなものを書いてしまい,それが適当に動いてしまったがために「再帰呼び出しを繰り返してもどこかで発行した return の値が最初の呼び出しまで戻る」とか勘違いしてしまったのが問題.その次の課題の二分探索のプログラムで結構な数の学生が再帰呼び出しに return を書いてくれないという状況に陥った.ま,再帰関数の説明の資料が void 型の関数だったので理解のしようもないのだけど(注:私は資料にノータッチ).
つか,それって再帰の深部で値を exception に乗せて throw で投げて再帰の外で catch するという exception-driven programming の思想だよね(注:普通の意味と違う).
- Newer: AWK - はじめ