4

このマクロを1つのカーネルコードで見つけました 。http://lxr.free-electrons.com/source/arch/alpha/include/asm/io.h?v = 3.0; a = arm#L140

#define IO_CONCAT(a,b)  _IO_CONCAT(a,b)
#define _IO_CONCAT(a,b) a ## _ ## b

これの意味がわからないのですが、誰か知っていますか?

編集 :

それからここにそれが返すもの

  return IO_CONCAT(__IO_PREFIX,readl)(addr);
4

3 に答える 3

9

ダブル ハッシュは、2 つのトークンを連結するために使用されます。

#define CONCAT(a,b) a ## b

CONCAT(x, y) # Gives 'xy'

ただし、渡される引数の 1 つがマクロ自体である場合、このような素朴な実装は機能しません。

#define Z y
CONCAT(x, Z) # Gives 'xZ', not 'xy' as one might expect

そのため、質問でマクロの間接化が使用されています。

#define CONCAT(a,b)  __CONCAT(a,b)
#define __CONCAT(a,b) a ## b

#define Z y
CONCAT(x, Z) # Gives 'xy' 

アップデート。

次に、質問している具体的な例を考えてみましょう。

return IO_CONCAT(__IO_PREFIX,readl)(addr);

これ__IO_PREFIXは明らかにマクロです (Linux カーネルの大文字の識別子は多くの場合マクロです)。いくつかの場所で定義されています。そのうちの1 つは次のとおりです。

#define __IO_PREFIX             generic

それでは、元のステートメントを拡張するためにどの手順が実行されるかを見てみましょう。

  1. 展開__IO_PREFIX:
    return IO_CONCAT(ジェネリック、readl)(addr);
    
  2. 展開IO_CONCAT(...):
    return _IO_CONCAT(generic,readl) (addr);
    
  3. 展開_IO_CONCAT(...):
    generic_readl (addr) を
    返します。
于 2012-08-30T14:13:53.920 に答える
5

それがトークンの貼り付けです。トークンを連結します。したがってIO_CONCAT(foo,bar)、に展開されfoo_barます。

これは、§6.10.3.3のC99で定義されています。

関数のようなマクロの置換リストで、パラメーターの直前または直後に##前処理トークンがある場合、パラメーターは対応する引数の前処理トークンシーケンスに置き換えられます。ただし、引数が前処理トークンで構成されていない場合、パラメーターは代わりにプレースマーカー前処理トークンに置き換えられます。)

オブジェクトのようなマクロ呼び出しと関数のようなマクロ呼び出しの両方で、置換リストを再検査して置換するマクロ名を増やす前に、置換リスト内の前処理トークンの各インスタンス##(引数からではない)が削除され、前の前処理トークンが連結されます次の前処理トークンを使用します。プレースマーカー前処理トークンは特別に処理されます。2つのプレースマーカーを連結すると1つのプレースマーカー前処理トークンになり、プレースマーカーを非プレースマーカー前処理トークンと連結すると非プレースマーカー前処理トークンになります。結果が有効な前処理トークンでない場合、動作は未定義です。結果のトークンは、さらにマクロを置き換えるために使用できます。##演算子の評価の順序は指定されていません。

于 2012-08-30T14:04:03.650 に答える
5

これは、プリプロセッサトークンの連結演算子です。

##'演算子は1##' preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of eachつのトークンに結合され、マクロ展開で`##'と2つの元のトークンが置き換えられます。通常、両方が識別子になるか、一方が識別子になり、もう一方が前処理番号になります。貼り付けると、より長い識別子になります。有効なケースはこれだけではありません。2つの数値(または数値と1.5やe3などの名前)を1つの数値に連結することもできます。また、+ =などの複数文字の演算子は、トークンの貼り付けによって形成できます。

于 2012-08-30T14:04:25.097 に答える