2012-02-26 12 views
0

私はこれが私達のマクロCマクロの展開はどのように機能しますか?

#define rsAssert(v) if(!(v)) printf("rsAssert failed: %s, in %s at %i" #v, __FILE__, __LINE__); 

ケース1でのサンプルコードで

を私の混乱を説明しましょう:

int main(void) 
{ 
    rsAssert(0); 
    return 0; 
} 

この場合は、正常に

ケース2

をコンパイル
int main(void) 
{ 
    rsAssert(0) // note here ; is not present 
    return 0; 
} 

これもsuccsfully 質問1コンパイル:それはあなたがそれらの間に差をrsAssert(0)を書きませんかrsAssert(0);か意味

を?


その後、

ここケース3

int main() 
{ 
    if(1) 
    rsAssert(0); 
    else 
    printf("mr.32"); 
    return 0; 
} 

rsassert(0);は、[コンパイルhttp://ideone.com/7dFv1]しかしを見に行くされていない;rsasser(0)が正常に動作せずに[私は

.. http://ideone.com/8fehl]見ますマクロexで何が起こっていないかここにパンション...

答えて

4

理由は次のとおりです。

int main() 
{ 
if(1) 
    if(!(v)) printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);; 
else 
    printf("mr.32"); 
return 0; 
} 

はからの最初のprintfの最後に余分なセミコロンに注意してください。マクロ。

通常、if文の後ろには単一の文、または{}を含むブロックが続きます。;

しかしので余分の

、あなたがこれを持っている:

余分なセミコロンが空文ですが、それでもまだ声明であることを
if (...) 
    printf(...); ; 
else 
    printf(...); 
return 0; 

マクロから。その後、物事はより意味をなさないでしょう。

+0

オハイオ州のおかげで、すべてのものが得られました。ケース1の場合、もう1つあります。空文であり、ケース2が完全であるがケース2の場合はrsassert(0)を使用する。ケースエクストラ;問題が発生します... –

+1

はい。簡単に言えば、Cでのマクロ置換を見ると、文字通りファイルにコピーされたばかりです。彼らは本当に自分のセマンティクスを持っていません。 –

2

ケース3では全く動作しません。手で展開しています(そしてそれが意味をなすためにのために再調整):

int main() 
{ 
    if (1) 
    if(!(0)) 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
    else 
     printf("mr.32"); 
    return 0; 
} 

あなたが見ることができるように、elseが間違っif文で終わります。 ifステートメントを含むマクロを機能させるには、単純なステートメントのようにする必要があります。 do... while(0)でそれをラップすると慣用句です:

#define rsAssert(v)               \ 
    do {                 \ 
     if(!(v))                \ 
     printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__); \ 
    } while (0) 
+1

+1はdo-while(0)を推奨します。 – jamesdlin

1
if(1) 
    rsAssert(0); // Original semicolon 
else 
    .... 

は、この余分なセミコロンは、新しい空のステートメントを引き起こしている

if(1) 
    if(!(v)) printf("rsAssert failed: %s, in %s at %i", 
     #v, __FILE__, __LINE__);; // Notice the extra semicolon. The extra from the 
           // macro expansion. 
else 
    .... 

に展開されます。 {}が存在しないので、if文の場合、elseは直ちに従わず、コンパイラが不平を言っています。だから、やる - これは実際にコンパイルなっているものですので、それはケース3で動作していない

if(1) 
{ 
    rsAssert(0); 
} 
else 
    .... 
4

これは私がプログラマーにすべてのif文で本文を使用させる最大の理由です。

int main() 
{ 
    if (1) 
    if(!(0)) 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
    else 
     printf("mr.32"); 
    return 0; 
} 

良いコーディング標準によって変化する列挙された打撃の低コストで

int main() 
{ 
    if (1){ 
    if(!(0)){ 
     printf("rsAssert failed: %s, in %s at %i", "0", __FILE__, __LINE__); 
     } 
    } 
    else { 
     printf("mr.32"); 
    } 
    return 0; 
} 

修正を防ぎます。

#define rsAssert(v) (printf((!v)?"rsAssert failed: %s, in %s at %i":"", #v, __FILE__, __LINE__)) 

これは動作しますが、常にprintfを実行します。

#define rsAssert(v) ((!v)?printf("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__):0) 

これはまた、次の点を考慮して、あなたがアサートをトリップ場合はプリントアウトしたが、

を探して厄介であるだろう!

if(rand()%2) 
    FooLog("Hello World"); 
ImportantFunction(); 

#if DEBUG 
#define FooLog printf 
#else 
#define FooLog // 
#endif 

リリースでは、重要な機能は時間の50%の時間の100%で動作します。

+0

ハッハッハ良いキャッチ... !!! –

+0

別のケースを追加しました。 – Nico

関連する問題