2017-07-27 11 views
1

この特定のコードでは、マクロを使用してCOUNTERクラスのすべてのメンバーに対してインクリメンタ関数を作成することにより、巧妙なことを行います。ダブルポンドはなぜこの場所には必要ですか?

class COUNTER 
{ 
    public: 
     UINT64 _call; 
     UINT64 _call_indirect; 
     UINT64 _return; 
     UINT64 _syscall; 
     UINT64 _branch; 
     UINT64 _branch_indirect; 

     COUNTER() : _call(0),_call_indirect(0), _return(0), _branch(0), _branch_indirect(0) {} 

     UINT64 Total() 
     { 
      return _call + _call_indirect + _return + _syscall + _branch + _branch_indirect; 
     } 
}; 

COUNTER CountSeen; 
COUNTER CountTaken; 

#define INC(what) VOID inC## what (INT32 taken) { CountSeen. what ++; if(taken) CountTaken. what ++;} 

INC(_call) 
INC(_call_indirect) 
INC(_branch) 
INC(_branch_indirect) 
INC(_syscall) 
INC(_return) 

私はマクロによって少し混乱しています。著者がマクロの関数定義部分でダブルポンドを使用し、インクリメントされるクラス変数として使用されていないときはどうしてですか?

編集:私は二重のポンドは、連結のためのものであることを得るが、私の混乱は、二重ポンドは 「CountSeen何++。」 と 「CountTaken何++。」 部分では不要である理由から来ています。

+0

短い答え:ダブルポンド記号( '##')は、連結のためのプリプロセッサ演算子です。 – DimChtz

答えて

1

のは、最初のマクロ(INC(_call))呼び出しがに展開するものを見てみましょう:ビットを再フォーマット

VOID inc_call (INT32 taken) { CountSeen. _call ++; if(taken) CountTaken. _call ++;} 

、我々が得る:

VOID inc_call (INT32 taken) { 
    CountSeen._call++; 
    if(taken) 
     CountTaken._call++; 
} 

これはCountSeen._callをインクリメント機能、inc_callを宣言し、多分またCountTaken._call。変数は._call(無効なトークンであり、ピリオドの付いた名前を開始できないため)と呼ばれないので、マクロ引数にピリオドを貼り付けるべきではありません。同様に、_call++は有効なトークンではないため(トークンは2つで、名前にプラス記号を含めることはできません)、そこにはポンド記号は使用しないでください。

ただし、最初の##がなければ、結果はVOID inc _call (INT32 taken)となります。これは2つの関数名を持つためC++も無効です。

+0

ああ、これは理にかなっています。ありがとうございました! –

0

ダブルポンドは、プリプロセッサの構文で2つの用語を連結できる構文です。ダブルハッシュ##を連結するために使用されている

#define foo(x) foo_##x 

void foo_1(); 
void foo_2(); 

... 

foo(1); // this will call foo_1 
+0

そうですが、 "CountSeen。what ++"や "CountTaken。what ++"の部分にはなぜ必要ないのですか? –

+0

@AnthonyCabrera:パーサは 'X.Y'を単一のトークンとして読み込むのではなく' X'、 '.'、および' Y'として読み込みます。 – GManNickG

+0

そこに連結する必要はないからです。すでに2つのトークンがあります。 – SergeyA

1

は、簡単な例を考えてみましょう。したがって

INC(_call) 

CountSeen. _call ++;CountSeen._call++;と同等であることが、inc _callinc_callと等価ではないことを

VOID inc_call (INT32 taken) { CountSeen. _call ++; if(taken) CountTaken. _call ++;} 

注に展開します。

関連する問題