Функциональные макросы и странное поведение

Я начал читать Effective C ++, и в какой-то момент в пункте 2 упоминается следующее:

// call f with the maximum of a and b
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

...

int a = 5, b = 0;
CALL_WITH_MAX(++a, b); // a is incremented twice
CALL_WITH_MAX(++a, b+10); // a is incremented once

Здесь число раз, которое a увеличивается перед вызовом f
зависит от того, с чем это сравнивается!

Действительно, если я использую простое утверждение печати в f7 печатается в первом звонке, но я не могу понять, почему. Я что-то упускаю из виду?

3

Решение

Компилятор заменяет макросы именно тем, что вы передаете, дословно. Таким образом, вы в конечном итоге

int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));
5

Другие решения

использование g++ -E myprog.cpp (заменить g++ с whatever-your-compiler-is если вы не используете g++) — он работает почти со всеми компиляторами, он будет производить реальный материал после предварительной обработки.

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

Вы бы получили гораздо больше того, что ожидали (вероятно), если бы использовали встроенную функцию:

 inline void CallWithMax(int a, int b)
{
f((a) > (b) ? (a) : (b));
}

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

Вы также можете пройти через встроенную функцию, если вы строите свой код с отладочными символами, поэтому, если вы хотите увидеть, какое значение a а также b на самом деле внутри функции, вы можете сделать это. Макросы, потому что они расширяются до исходного места в исходном коде, так что вы не можете реально увидеть, что происходит внутри.

1

По вопросам рекламы [email protected]