4

私はかなり長い間 C でプログラミングを行ってきました。そのため、gcc コンパイラ拡張機能について聞いた高度な CI を少し学ぶことにしました。以下に、今まで次のように実装した MAX() のコードを見ました。

#define MAX(x,y) ((x) > (y)? (x): (y))

これは私が見つけた新しい定義です。残念ながら、以下のコードが何をするのかさえ理解できませんか? そして、なぜ私は上記の代わりに以下のようにするのでしょうか?

#define MAX(a,b)                    \
    ({                              \
    typeof (a) _a = (a);            \
    typeof (b) _b = (b);            \
    _a > _b ? _a : _b; })
4

3 に答える 3

8

利点は、従来のマクロのように何度も引数を評価することを回避できることです。

ローカル変数を導入する (typeof引数の型を「複製」するために使用する) ことで、実際の式は 1 回だけ評価され、戻り値は入力式を再度評価するのではなく、単純にローカル変数を使用します。 .

次のように呼び出された場合に何が起こるかを比較します。

int a = 0, b = 1;
const int c = MAX(++a, ++b);

最初のケースでは、入力式に副作用があるため、結果を予測するのは困難です。2 番目のケースでは、引数は 1 回だけ評価されるため、すべてがMAX()通常の関数であるかのように動作します。

また、最初のマクロの例では、引数をどこでも括弧で囲むことができず、危険です。

于 2013-06-11T08:13:24.210 に答える
3

これは、int や float などのさまざまなデータ型で機能する汎用マクロの例です。たとえば、次のようになります。

int i = 10;
int j = 20;
int k = MAX(i, j);

次のように展開されます。

int i = 10;
int j = 20;
int k = ({ int _a = (i); int _b = (j); _a > _b ? _a : _b; });

一方:

float x = 10.0f;
float y = 20.0f;
float z = MAX(x, y);

次のように展開されます。

float x = 10.0f;
float y = 20.0f;
float z = ({ float _a = (x); float _b = (y); _a > _b ? _a : _b; });

混合データ型でも機能します。

int i = 10;
float y = 20.0f;
float z = MAX(i, y);

さまざまなデータ型をサポートするだけでなく、単純なマクロの厄介な副作用も回避します。

#define MAX(a, b) (((a) > (b)) ? (a) : (b)))

たとえば、次のように呼び出すと、望ましくない動作をします

int k = MAX(i++, j++);

さらに、式を引数として渡すと、より効率的になります。

float x = 10.0f;
float y = 20.0f;

float z = MAX(sin(x), sin(y));

引数は 1 回しか評価されないためです。

于 2013-06-11T08:14:45.107 に答える
3
typeof (a) _a = (a);            \
typeof (b) _b = (b);            \

a同じ型のandを持つ 2 つの変数を作成して、b2 回評価されるのを回避します。

より詳しい情報

インライン関数の最も明白な候補は、プリプロセッサ マクロです。GCC のインライン関数はマクロと同様に機能し、さらに型チェックを受けます。たとえば、このマクロの代わりに:

#define max(a,b) ({ a > b ? a : b; })

対応するインライン関数を使用できます。

static inline max (int a, int b)
{
        if (a > b)
                return a;
        return b;
}
于 2013-06-11T08:20:06.493 に答える