標準出力に値を出しながらデバッグをする、いわゆるprintf debugしてた時の話です。
こんなソースが有りました。
void move(){
std::cout << player.move() << std::endl;
}
move()はプレイヤの座標を移動させる関数です。
普段は0を返しますが、壁にあたったりしてmove()が失敗すると1を返すわけです。
で、壁にあたってないのに1を返したり、移動してないのに0を返したりと
move()の動作がどうもおかしいので、返り値を表示するようにしています。
また、移動後の座標も一緒に表示するようにしました。
void move(){
std::cout << player.move() << "(" << player.getx() << "," player.gety() << ")" << std::endl;
}
予想通り座標もおかしい。
で、調べていましたが、何故か違和感が…。
先ほどのコードはmove()を実行した後の座標がほしいわけなのですが、
何故かmove()を実行する前の座標が表示されているようです。
気がついた人はいると思いますが、この書き方は未定義動作を含みます。
具体的には、move(),getx(),gety()はどの順序で呼び出されるかわかりません。
言語仕様としては、実装依存、ということですね。
副作用のある関数(内部状態を変更する関数)は単独で使うようにしましょう。
よって、こういう風に書き換えると想定通りに動きました。
void move(){
auto moveresult = player.move();
std::cout << moveresult << "(" << player.getx() << "," player.gety() << ")" << std::endl;
}
move()のバグはまだとれてません。