一部のマクロステートメントでC ++で予期しない結果が生じることがありますか?

どのマクロステートメントが予期しない結果を引き起こす可能性がありますか?

#define YEAR_LENGTH   365
#define MONTH_LENGTH  30
 #define DAYCALC(y, m, d) ((y * YEAR_LENGTH) + (m * MONTH_LENGTH) + d)

 int main()
 {
    int x = 5, y = 4 , z = 1;
    cout << DAYCALC(x *3 , y %3 , z) << endl ;
    cout << DAYCALC(x +12 , y  , 300) << endl ;
    cout << DAYCALC(x , 40 - y , 3+z) << endl ;
    cout << DAYCALC(x  , y  , (z+50)) << endl ;
    cout << DAYCALC(x  , y %3 , z) << endl ;
    cout << DAYCALC(4 % x , y++ , z) << endl;
    return 0;
 }

私は予期せぬ結果を伴わずにプログラムをうまく実行します。

いくつかの隠れた例外はありますか?

2
追加された 著者 Keith Thompson,
これは宿題の質問ですか? 1つのように見えますが、1つのタグは付けられていません。
追加された 著者 celtschk,
これがC ++の場合は、マクロではなくインライン関数を使用する必要があります。
追加された 著者 tenfour,

3 答え

オペレータの優先順位の問題があります。マクロは文字通りテキストコピーとペーストとして展開されます。

例えば:

DAYCALC(x , 40 - y , 3+z)

次のように展開されます:

((40 - y * YEAR_LENGTH) + (x * MONTH_LENGTH) + 3+z)

40 -y * YEAR_LENGTH は、演算子の優先順位のために必要なものではありません。

したがって、マクロ内のパラメータの周りに()を配置する必要があります。

#define DAYCALC(y, m, d)     (((y) * YEAR_LENGTH) + ((m) * MONTH_LENGTH) + (d))

一般に、マクロパラメータがマクロ内で複数回出現する場合、(最後のステートメント内の) y ++ などの副作用も複数回適用されます。だからそれは慎重になるべきことです。

8
追加された

g ++ -Eでマクロ展開後の動作を確認することができます。

int main()
{
int x = 5, y = 4 , z = 1;
cout << ((x *3 * 365) + (y %3 * 30) + z) << endl ; 
cout << ((x +12 * 365) + (y * 30) + 300) << endl ;
cout << ((x * 365) + (40 - y * 30) + 3+z) << endl ; //precedence problem
cout << ((x * 365) + (y * 30) + (z+50)) << endl ; 
cout << ((x * 365) + (y %3 * 30) + z) << endl ;
cout << ((4 % x * 365) + (y++ * 30) + z) << endl;
return 0;
}
7
追加された

DAYCALCを変更する必要があります。

#define DAYCALC(y, m, d) ( ((y) * YEAR_LENGTH) + ((m) * MONTH_LENGTH) + (d) )

そうすれば、もしmが3 + zならば、内側の項は正しいでしょう。

(3+z) * MONTH_LENGTH

間違ったものではない。

3 + z*MONTH_LENGTH
2
追加された