テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(macro-of-inline report) non-void返し対応の罠: 変数宣言

昨晩, non-void返し関数も, void返し関数に変換しちゃえばいいのでは?でも, 関数呼び出し側のコード変更がやばいよねという話をした.

(macro-of-inline report) 非void返しへの適用案 - テストステ論

ふと, 罠を思いついた. 時間がないので要点だけ書く.

int x = f()
int y = x + 1;
...

のようなコードを仮に, 正直に,

int x;
f(&x);
int y = x + 1;

のように変更したとする. これは, コンパイラによってはコンパイル出来なくなる.

int x;
int y;
f(&x);
y = x + 1;

のように変更しなければいけない.

もし, 変数宣言がブロックの前に並んでいるということが確定していれば, これは間違いなく出来そうである. しかし, 以下のように行儀の悪いコード(前のやつを少し拡張してある)については, どうだろうか?これは少し工夫が必要となる.

int x;
x = f(g());
int y = x + 1;

これは以下のようなアルゴリズムにすれば(昨日の拡張), 行儀の良い場合と共通化出来る.

(1) 初期値ありの変数宣言を, 宣言と代入に分解する.

int x;
x = f(x)
int y;
y = x + 1

(2) 宣言を前に繰り上げる.

int x;
int y;
x = f(g());
y = x + 1;

(3) 関数の引数内で呼び出されている関数呼び出しについて, 適当な変数を与えて外に出す. この時, 変数宣言は, blockの先頭にinsertする.

int hoge;
int x;
int y;
hoge = g();
x = f(hoge);
y = x + 1;

(4) 代入文について, void返しの呼び出しに変形する

(ry
g(&hoge);
f(hoge, &x);
y = x + 1;

これならばあとは, (3)の部分だけなんとか出来るなら, なんとか出来そう. 考えるだけは考えたので, あとはとりあえずやってみて嵌るという作業になるか. inline関数のマクロ変換はなかなか楽しい. 心がぴょんぴょんして眠れませんでした.