Почему макрос 'max' определяется так в C? - PullRequest
8 голосов
/ 16 марта 2011
 #define max(a,b) \
   ({ typeof (a) _a = (a); \
       typeof (b) _b = (b); \
     _a > _b ? _a : _b; })

Почему бы не просто (a>b ? a : b)?

Ответы [ 4 ]

19 голосов
/ 16 марта 2011

потому что otherwhise max(f(1), f(2)) будет вызывать одну из двух функций дважды:

f(1) > f(2) ? f(1) : f(2)

вместо этого, "кэшируя" два значения в _a и _b, у вас есть

({
    sometype _a = (a);
    sometype _b = (b);

    _a > _b ? _a : _b;
})

(и, как уже указывали другие, такая же проблема существует с автоинкрементом / автоопределением)

Я не думаю, что это поддерживается Visual Studio таким образом.Это сложное утверждение.Прочитайте здесь имеет ли msvc аналог gcc ({})

Я добавлю, что приведенное здесь определение составного оператора в руководстве по gcc http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62 показывает код ОЧЕНЬпохож на один вопрос для макс: -)

8 голосов
/ 16 марта 2011

Обходит главную проблему таких вещей, как

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

когда вы звоните с:

int x = max (a++, b--);

Так как это простая подстановка текста, это приводит к:

int x = ((a++) > (b--) ? a++ : b--);

что не что вы хотите.

Используя:

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

он использует временные переменные, которые фактически дают вам:

int x = ({ int _a = a++; int _b = b--; _a > _b ? _a : _b; })

, который запускает только побочные эффекты один раз.

Но, если честно, вам следует вообще отказаться от этого макроса и использовать функцию inline или даже не встроенную функцию, поскольку в большинстве случаев компилятор может выполнять достойную работу по оптимизации даже без этого предложения.

3 голосов
/ 20 октября 2011

Другой способ определения максимального (по крайней мере, для положительных чисел)

#define MAX(a,b) sizeof(union x { char ca[a]; char cb[b];})

Поскольку a и b доступны только один раз, MAX (a ++, b ++) дает правильный результат.

1 голос
/ 16 марта 2011

Если макрос вызывается с выражением, это может привести к неожиданному поведению. Предположим это:

int c = max(i++, j++);

В этом случае максимальное значение увеличивается вдвое при использовании более простой версии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...