Я хочу сделать простой макрос с #define для возврата меньших из двух чисел.
Как я могу сделать это в C? Предложите некоторые идеи и посмотрите, можно ли сделать это более запутываемым также.
Для слегка запутанных попробуйте следующее:
#define MIN(a,b) ((((a)-(b))&0x80000000) >> 31)? (a) : (b)
Обычно он вычитает их и рассматривает знаковый бит как 1 или 0. Если в результате вычитания получается отрицательное число, первое параметр меньше.
Обычно:
#define min(a, b) (((a) < (b)) ? (a) : (b))
Имейте в виду, что минимальная оценка выполняется дважды, что и было причиной катастрофы в недавнем вопросе .
Но зачем вам его запутывать?
Он сохраняет результат в переменной и оценивает каждый аргумент только один раз. По сути, это встроенная функция для бедняков + объявление:
#define min(t, x, a, b) \
t x; \
{ \
t _this_is_a_unique_name_dont_use_it_plz_0_ = a; \
t _this_is_a_unique_name_dont_use_it_plz_1_ = b; \
x = _this_is_a_unique_name_dont_use_it_plz_0_ < \
_this_is_a_unique_name_dont_use_it_plz_1_ ? \
_this_is_a_unique_name_dont_use_it_plz_0_ : \
_this_is_a_unique_name_dont_use_it_plz_1_ ; \
}
Используйте это как:
min(int, x, 3, 4)
/* x is an int, equal to 3
Just like doing:
int x = min(3, 4);
Without double evaluation.
*/
Конечно, вы можете используйте для этого #define, но зачем вам это нужно? Проблема с использованием #define, даже с круглыми скобками, заключается в том, что вы получаете неожиданные результаты с таким кодом (хорошо, на самом деле вы бы этого не сделали, но это иллюстрирует проблему).
int result = min(a++, b++);
Если вы используете C ++, а не C, безусловно, лучше использовать встроенную функцию, которая (i) избегает оценки параметров более одного раза и (ii) безопасна по типу (вы даже можете предоставить версии, принимающие другие типы значений , например беззнаковое, двойное или строковое).
inline int min(int a, int b) { return (a < b) ? a : b; }
Мне кажется этот метод довольно симпатичным:
#define min (a, b) (((a) + (b) - fabs ((a) - (b))) * 0.5)
И, просто для примера, пример на GNU C:
#define MAX(a,b) ({ \
typeof(a) _a_temp_; \
typeof(b) _b_temp_; \
_a_temp_ = (a); \
_b_temp_ = (b); \
_a_temp_ = _a_temp_ < _b_temp_ ? _b_temp_ : _a_temp_; \
})
Он не обфусцирован, но я думаю, что это работает для любого типа, в любом контексте, на (почти, см. комментарии) любых аргументах и т.д.; пожалуйста, поправьте, если сможете придумать контрпримеры.
Если бы я просто пытался слегка затушевать это, я бы, вероятно, выбрал что-то вроде:
#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0))
Я думаю, что решение Дойнакса тоже довольно симпатично. Обычные оговорки для обоих по поводу того, что аргументы макроса оцениваются более одного раза.