2016-07-06 6 views
0

私はいくつかのコードを見ていて、全体のロジックがここで意味をなさないと思う。このようなマクロを持つのはかなり貧弱です。 例として、このマクロを2回使用して、両方の文字列を出力します。マクロ内の静的変数

TESTING("hello"); 
TESTING("world"); 
  1. プリプロセッサは、単にコードのブロックと識別子を置き換え、それがコードをペースト/コピーと同じであるので、このマクロを使用する場合、コンパイラは、FirstPassのために再定義エラーを与えるべきではありません複数回? (手動mainstatic bool firstPass = true;複数回に貼り付けると、コンパイラはエラーになります。)

  2. firstPassstaticであれば、それは一度だけ作成され、初期化されます。このマクロを複数回使用すると、フラグがfalseに設定されているため、(最初の使用以外に)結果が生成されることはありませんが、毎回coutになります。

少し混乱します。

#define TESTING(input)       \ 
{            \ 
    static bool firstPass = true;     \ 
    if (firstPass) {        \ 
    std::cout << input;       \ 
    firstPass = false;       \ 
    }            \ 
} 
+4

を印刷します関数テンプレートの代わりにマクロを使用するのは悪いことです。 – LogicStuff

+3

このコードは無意味です。あなたがそれを呼び出すたびに、スコープの規則のために新しい 'firstPass'があります。 – NathanOliver

+1

あなたの誤解は、マクロそのものではなく、マクロの内容(特にブロック '{...}')にあるようです。つまり、手動でマクロの内容をコピーして貼り付けると、マクロの問題がなくなります。 – chris

答えて

4

このマクロは意図したとおりに動作しません。コンパイラが許可する理由の鍵は、static bool firstPassを囲む{ }です。これにより、新しいスコープが作成され、その新しい変数はその名前で他の変数を隠すことができます。スコープが終了すると、スタティックは表示されなくなります。そのため、新たなスコープの

が、これは合法である:

void f() 
{ 
    int i = 0; 
    { 
     int i = 1; 
     { 
      int i = 2; 
     } 
    } 
} 

これはマクロのうち、FirstPassのを移動することで、それが意図されたように動作します。

static bool firstPass = true; 
#define TESTING(input)       \ 
{            \ 
    if (firstPass) {        \ 
    std::cout << input;       \ 
    firstPass = false;       \ 
    }            \ 
} 

ETA:または意図したように、多分それは仕事をしません。マクロ内の静的なブールでは、各呼び出しサイトはfirstPassフラグの独自のインスタンスを持つため、各呼び出しサイトはその出力を正確に1回出力します。マクロの外側にある静的なブールでは、到達する最初のコールサイトのみが出力され、最初に到達したときにのみ報告されます。

だから、マクロ内部の静的なブール値で、

f() 
{ 
    for (int i = 0; i < 1000; ++i) 
    { 
     TESTING("A\n"); 
     TESTING("B\n"); 
     TESTING("C\n"); 
    } 
} 

int main() 
{ 
    for (int i = 0; i < 5; ++i) 
     f(); 
    return 0; 
} 

A 
B 
C 

を印刷しますが、マクロ外の静的ブール値で、それは、はいのみ

A 
+0

面白い;私はそれが意図したとおりに正確に動作すると言いたい。それぞれの 'TESTING'呼び出しが最初に呼び出されると、実行されたと報告されます。しかし、問題は「意図された行動は何か」になります。私たちはどちらも正しいです(何が意図されているかについての私たちの仮定のため)。彼らは、意図されているものについて異なる解釈や仮定しかしていません。 –

+0

ああ、私は、特定のコールサイトで最初に報告するという意図は考えていませんでした。 –