Существует несколько проблем с использованием макросов таким, какой вы есть.Идея, лежащая в основе макросов, заключается в том, чтобы упростить кодирование, поскольку нет проверок типов, которые чреваты опасностью:
Проблема - нет проверок типов:
#include <stdio.h>
#define max(a,b) ((a) > (b) ? (a):(b))
int main()
{
int a = -1;
unsigned int b = 2;
printf("The max is: %d\n", max(a,b));
return 0;
}
Вывод довольно неопределенный.gcc выводит -1
Проблема - двойная оценка
Двойная оценка происходит, когда ваши макропараметры НЕ являются простыми переменными, например:
#include <stdio.h>
#define max(a,b) ((a) > (b) ? (a):(b))
int main() {
int a = 1, b = 2;
printf("max(%d, %d) = %d\n", a, b, max(a, b));
printf("max(%d, %d) = %d\n", a, b, max(a++, b++));
printf("max(%d, %d) = %d\n", a, b, max(a, b));
return 0;
}
Если вы смотрите наmid(a,b,c)
это еще хуже.
Заключение
Пожалуйста, не пишите такой код.
Если вы придерживаетесь компилятора, где нет нестандартный оператор typeof
, тогда лучше использовать stdtypes.h и stdint.h и объявить функции:
#define __declare_min(__type) __inline__ static __type min_ ## __type(__type a, __type b) { return a < b ? a : b; }
__declare_min(uint32_t)
__declare_min(int64_t)
, и вы можете использовать их явно:
int main() {
printf("%u", min_uint32_t(3, -5));
printf("%d", min_int64_t(-1, -5));
}
Если у вас есть компилятор с оператором типа typeof
, вы можете использовать:
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
GCC-специфичный
Если вы используете достаточно новую версию gcc - скорее всего,если вы используете gcc, то вы - вы должны использовать __auto_type
вместо typeof
:
#define max(a,b) \
({ __auto_type _a = (a); \
__auto_type _b = (b); \
_a > _b ? _a : _b; })
Для gcc typeof справочной страницы] 1 :
Использование __auto_type
вместо typeof
имеет два преимущества:
Каждый аргумент макроса отображается только ве в расширении макроса.Это предотвращает экспоненциальный рост размера макроса, когда вызовы таких макросов вложены в аргументы таких макросов.
Если аргумент макроса имеет изменяемый тип, он оценивается только один раз при использовании __auto_type, но дважды, если используется typeof.
C ++
Это совсем другое обсуждение :-)