2012-04-15 2 views
6

難解に#defineマクロは

29 #define get_cpu_var(var) (*({       \ 
30   extern int simple_identifier_##var(void);  \ 
31   preempt_disable();        \ 
32   &__get_cpu_var(var); })) 

以下のように定義されてget_cpu_var marcroが、それは変数のポインタを返す関数マクロの一種だったと仮定していますbe.Iする不可解なようだ(上のベースアスタリスク)、それは何らかの関数ポインタなのでしょうか?私もそれに近いですか?誰でも私を啓発できますか? GCCコンパイラの非標準機能、1は、Cの式に複合文を埋め込むことができます - あなたは開口部({})を閉じる間の参照は何

答えて

15

文の表現です。そのような文の式の結果は、({})の最後の式の文です。あなたの場合は&__get_cpu_var(var)になります。

&演算子は、__get_cpu_var(var)サブ式の結果に適用されます。つまり、__get_cpu_varは左辺値を返します。これが確かにCならば、__get_cpu_varもマクロでなければなりません。なぜなら、C言語関数ではlvaluesを返すことができないからです。

演算子は、上記のマクロ定義の冒頭にある*演算子によって参照解除されるポインタ(文全体の式の結果)を生成します。したがって、上記のマクロは基本的に*&__get_cpu_var(var)の式と同等です。

__get_cpu_var(var)以外にも、*&__get_cpu_var(var)というように実装されている理由があります。これはルーテンスの結果を__get_cpu_var(var)に保存するために行われます。文の式の結果は、({})内の最後のstetementが左辺値だったとしても、常に右辺値になります。結果の有益性を保つために、よく知られている*&トリックが使用されます。

このトリックは、GCCステートメントの表現に限定されません。これは、通常の日常的なCプログラミングで比較的頻繁に使用されます。たとえば、2つの変数

int a, b; 

を持っていて、セレクタ変数selectに応じて、(我々はそれに42を割り当てたいとしましょう)左辺値としてaまたはbのいずれかを返す式を書きたいと想像。 C言語で?:オペレータがそのオペランドのlvaluenessを失うので、これは、動作しません

(select ? a : b) = 42; 

を次のように素朴な試みが見えるかもしれません。結果は右辺値になります。右辺値は代入できません。このような状況では*&トリックは救助

*(select ? &a : &b) = 42; 

に来て、意図したように、今では動作します。

元のポスターのマクロ定義には、一見冗長な*のアプリケーションと&のアプリケーションが含まれています。そのため、あなたはassgnmentだけ右側にget_cpu_varを使用することができるだろうというトリックなし

something = get_cpu_var(something); 
get_cpu_var(something) = something; 

のいずれかの側に上記get_cpu_varマクロを使用することができます。

C++言語では、参照を使用すると同じ効果が得られます。 Cでは参照がないので、代わりにこのようなトリックを使用します。

+0

*(...)は結果の型変換ですか? *編集しました。記入してありがとうございます。 –

+0

これは基本的に '*&__get_cpu_var(var)'を返しますが、なぜ単に '__get_cpu_var(var)'を返さないのですか?コンパイル時の型チェックのいくつかの種類? – Anthales

+1

@Anthales:私は答えを上記に加えました – AnT

関連する問題