さて,Assertion の説明も最終回となりました.
今回は,唯一気をつけなければいけないことを説明しようと思います.
既に assert は,NDEBUG マクロを定義するとなかったことにされることは説明しました.
それでは,次のようなコードはどうなるでしょうか?
ポインタが出てくるのでがんばってください(^^;
// #define NDEBUG #include <assert.h> #include <stdio.h> enum tagBOOL { true = -1, false = 0 }; typedef enum tagBOOL bool; bool checked_swap(int* a, int* b) { int tmp; if( a == NULL || b == NULL ) { return false; } tmp = *a; *a = *b; *b = tmp; return true; }; int main(int argv, char* argc[]) { int a = 1, b = 2, *pa, *pb; pa = &a; pb = &b; printf("a=%d, b=%d\n", a, b); assert( checked_swap( pa, pb) == true ); printf("a=%d, b=%d\n", a, b); return 0; }
ここで
enum tagBOOL { true = -1, false = 0 }; typedef enum tagBOOL bool;
というのは,C言語には bool 型がないので(C99にはあるみたい?)C++風に使えるように自分で勝手に定義しているだけです.
checked_swap 関数は,二つの int 型ポインタを引数に取り,2つのポインタの中身を入れ替える関数です.
ただし,ポインタが NULL のときは関数が false (偽)を返して処理が失敗したことを伝えます.
逆に成功したときは true を返します.
さて,次がポイントです.
assert( checked_swap( pa, pb) == true );
これは,checked_swap 関数が常に真であることを表明しています.
このままコンパイルして実行するとこうなります.
>gcc assert.c >assert a=1, b=2 a=2, b=1
プログラム自体はコンパイルできるし,処理にも一見おかしいところは見当たりません.
それでは,最初のコメントアウトをはずしてコンパイル,実行してみましょう.
>gcc assert.c >assert a=1, b=2 a=1, b=2
よく見てみると・・・ checked_swap 関数が動いていません.
もうお分かりですね?
NDEBUG マクロを定義したおかげで assert が何もしない命令に置き換えられたため,assert の条件部分に書いた checked_swap 関数が呼び出されなくなってしまったのです.
従って,上記のプログラムの main 関数を正しく書き直すとこうなります.
int main(int argv, char* argc[]) { int a = 1, b = 2, *pa, *pb; pa = &a; pb = &b; printf("a=%d, b=%d\n", a, b); bool swap_was_success = checked_swap( pa, pb); assert( swap_was_success == true ); printf("a=%d, b=%d\n", a, b); return 0; }
これで,デバッグモードでもリリースモードでも共通のコードが使えるようになりました.
めでたしめでたし(^^
これを機会にどんどん assert を使っていきましょう.
ではでは.