2010-12-15 9 views
0

別のマクロの値に基づいてコンパイル時にマクロを定義したいと思います。予想通りしかし、このコードが実行されない:奇妙なマクロ定義の問題

max = 2 
0 
1 
2 
... 

を、それが単に印刷しなければならない場合、終了まで継続:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define SIXTEEN 16 
#define TWO (SIXTEEN % 8 == 0)? (SIXTEEN/8) : ((SIXTEEN/8) + 1) 

int main(); 

int main() { 
    printf("max = %d\n", TWO); 
    int i; 
    for (i = 0; i < TWO; i++) { 
     printf("%d\n", i); 
    } 
    return 0; 
} 

これは印刷

max = 2 
0 
1 

と出ます。私が代わりにこれを行う場合は

、それが動作します:

#define TWO 2 

が、私はこれはマクロの定義の問題だと思った...しかし、私は元の#defineで次の操作を行う場合、それはに思えます仕事:

誰でもここで起こっていることを説明できますか?

答えて

11

問題は、トークンTWOがマクロを定義していると、トークンによって置き換えられていることであるので、この:

i < TWO 

はこのようになりますので、演算子の優先順位の

i < (SIXTEEN % 8 == 0)? (SIXTEEN/8) : ((SIXTEEN/8) + 1) 

、これはあります

(i < (SIXTEEN % 8 == 0)) 
    ? (SIXTEEN/8) 
    : ((SIXTEEN/8) + 1) 

のように余分な括弧が必要ですマクロを使用する場合は

#define TWO ((SIXTEEN % 8 == 0)? (SIXTEEN/8) : ((SIXTEEN/8) + 1)) 
      ^             ^

、それはどこのことができます。結果は、あなたが期待するものであることを確認するために括弧を使用するのが最善です:は、その置換リストに置き換えられ、あなたが望む結果を得ます。

+0

+1 37秒で私を打つ。 =( –

+2

+1一般的な経験則は、マクロが式に展開されることになっている場合、(マッチングする)ペアの括弧で囲まれていることを確認します。ただし、1つのトークンに展開することが保証されているOPのSIXTEENマクロのように)。 –

1

マクロを展開し、マクロ展開後にforループを見て:

for (i = 0; i < (16 % 8 == 0)? (16/8) : ((16/8) + 1); i++) 

を参照してください? i < (16 % 8 == 0)は、?:演算子の条件です。 TWOの定義の前後に括弧を入れる必要があります。

2

常に使用するコンテキストがわからないため、かっこで囲んでください。隣接する演算子の優先度が高く、マクロが正しく評価されない可能性があります。

#defineのdシンボルが5または"hello world"のような単一のトークンである場合にのみ、かっこは使用されません。

単一のトークンだけでなく、式である引数を使用してマクロを呼び出す場合は、上記と同じ理由で、その引数のすべてのカッコをカッコで囲みます。

もう1つのことは、副作用がマクロ引数として渡されることです。対応するマクロ引数が定義内で複数回参照されている場合、評価は複数回実行され、通常はそれが望ましいものではありません。