Войти
ПрограммированиеПодсказкиОбщееОбщее

Коварные макросы

Автор:

Всем известен макрос

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

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

Проиллюстрирую на примере, который сам проверял:

#define max(a, b) (((a) > (b)) ? (a) : (b))
int globalVal = 0;
int f(int a)
{
  globalVal++;
  return a;
}
int main()
{
  int res = max(f(2), 1);// по выполнении этой операции globalVal будет равен двум!
  return 0;
}

Вот и делайте выводы — использовать макрос или функцию ;)

PS. То же самое, разумеется, относится и к макросу min и многим другим.

#макросы

12 марта 2008 (Обновление: 9 июня 2009)

Комментарии [25]

Страницы: 1 2 Следующая »
#1
10:02, 9 июня 2009

Мда, это в любой книге "цпп за 5 дней" описано вообще-то ;-)

#2
11:21, 9 июня 2009

Спасибо, Капитан!

#3
11:23, 9 июня 2009

du_hast
> Спасибо, Капитан!
+1  :)

#4
11:44, 9 июня 2009

Неуправляемые побочные эффекты, как обычно.

#5
16:57, 9 июня 2009

подсказка была отправлена ещё бог знает сколько лет назад :)
чёрт с вами, исправил
>немногим
на
>не каждому

#6
18:16, 9 июня 2009

КО: А вообще есть std::min() и std::max().

#7
18:29, 9 июня 2009

нет дефайнами так уже давно многие не пользуются
слишком много подводных камней из за типов.
шаблонами я такое решаю.

#8
18:35, 9 июня 2009

DanQuimby

О!

template <class U, class V> ??? min(U const & lhs, V const & rhs) { return (lhs < rhs) ? lhs : rhs; }
#9
18:40, 9 июня 2009

JohnSmith
+1 ))))

кстати у меня не компилится просто std::min(a, b) приходится явно указывать std::min<type>(a, b)
при этом если не пишу std:: , то все компилится, но в таком случае я не уверен что в данном месте не подставляется макрос min.

как быть?

#10
19:45, 9 июня 2009

du_hast
>O!

А если так)

template<bool,class T, class H>
struct select{ typedef T type; };
template<class T, class H>
struct select<false, T, H>{ typedef H type; };

template<class T, class H>
struct _outtype
{
    typedef typename select<(sizeof(T) > sizeof(H)), T, H>::type type;
};

template <class U, class V> typename _outtype<U, V>::type min(U const & lhs, V const & rhs)
{ return (lhs < rhs) ? lhs : rhs; }
#11
19:55, 9 июня 2009

Кавайные макросы :3

#12
19:59, 9 июня 2009

asm
du_hast
нехорошо , если будут сравнивать int и unsigned - может получится неверный результат (в асме нету команд сравнения, чтобы один операнд знаковый, а другой беззнаковый)

#13
22:53, 9 июня 2009

asm
Так плохо. Тип должен быть один. А если кто-то пытается сравнивать разные типы, то при допустимом кастовании одного типа в другой все отработает как надо. Ну а если нет такого каста, значит сравнивать низя.

#14
23:38, 9 июня 2009

San
> А если кто-то пытается сравнивать разные типы, то при допустимом кастовании одного типа в другой все отработает как надо.

будет cannot deduce template parameter T.

Страницы: 1 2 Следующая »
ПрограммированиеПодсказкиОбщееОбщее

Тема в архиве.