#defineの使用上の注意

1053 ワード

昨日C++でプログラムを書いた時、使ってしまいました.
#defineMAX(a,b)   a>b?a:b

このマクロは、a、b間の最大値を求める文を定義していることは明らかであり、通常、これは1つの関数を単独で書くよりも効率的であるべきである(関数呼び出しにはスタックアウトスタックの操作が必要である).このような文は以前何度も使ったことがあるので、大丈夫だと思います.しかし、私はプログラムにこのようなコードを持っています.
int a =Height(p->left);
int b =Height(p->right);
p->height =MAX(a,b)+1;

デバッグの結果、ここまで実行されるたびに、MAXが返す値は常にエラーであることがわかりました.簡単に言えば、
int a = 0;
int b = -1;
int c =MAX(a,b)+1;

本来ならば、このときcは1であるべきで、現在のcは0である.
どうしてこんなことになったの?その時葛藤して、それがマクロ定義の問題だと悟った.マクロ定義をこのように変更しました.
#defineMAX(a,b)  (a>b?a:b)

その後のマクロ定義を変更すると、完全に正常に動作します.
理由は次のとおりです.
マクロ定義は実は置換の過程であり、コードがコンパイルされると、コンパイラはすべてのMAXが現れた場所を私が定義した文に置き換えます.つまり、上記の3つの文は、次の文に置き換えられます.
int a = 0;
int b = -1;
int c = a>b?a:b+1;

このときの比較は確かにaとbであるが,戻りはaとb+1であり,このときa=0,b=−1であり,コロン前の式,すなわちaをとることがわかる.したがって、戻り値は常に0であり、1ではありません.
解決方法も簡単で、上に書いたように、マクロ定義に括弧を付けるだけでいいので、マクロ全体を独立させ、置換後のコードとつなぎ合わせて論理エラーが発生しません.
作者のブログ:クリックしてリンクを開く