Подтвердить что ты не робот

Что такое оценка аргументов?

Герберт Шильдт говорит:

В некоторых ситуациях вместо функции-типа-макроса следует использовать реальную функцию, например: где размер кода должен быть сведен к минимуму или где аргумент не должен оцениваться более одного раза.

Что он подразумевает под "аргументом не следует оценивать более одного раза?"

4b9b3361

Ответ 1

Возьмем макрос для вычисления максимума двух значений:

#define MAX(a, b) ((a) < (b) ? (a) : (b))

Затем мы используем его следующим образом:

int x = 5;
int y = 10;
int max = MAX(x++, y++);

Затем макрос расширяется до

int max = ((x++) < (y++) ? (x++) : (y++));

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


Еще один важный момент - использование скобок в макросе. Возьмем еще один простой макрос:

#define MUL(a, b) a * b

Теперь, если вы вызываете макрос как

int sum = MUL(x + 3, y - 2);

то разложение становится

int sum = x + 3 * y - 2;

Что из-за приоритета оператора равно

int sum = x + (3 * y) - 2;

Часто не совсем то, что ожидалось, если ожидать (x + 3) * (y - 2).

Эта проблема также "решена" с помощью функций.

Ответ 2

Иногда аргументы имеют побочные эффекты.

Например, значение i++ равно i, но i увеличивается на 1. В результате значение следующего i++ будет i + 1.

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

При выполнении функции вы не заботитесь о побочных эффектах. Тем не менее, неявное продвижение по типу и литье могут быть подвержены ошибкам.