Вопрос
ПРИВЕТ ,
Может ли кто-нибудь помочь мне понять, почему значение SQUARE(x) равно 49?
Я использую Visual C++ 6.0.
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
Решение
Нил Баттерворт, Марк и Павел правы.
SQUARE(++y) расширяется до ++y * ++y, что увеличивает значение y в два раза.
Еще одна проблема, с которой вы можете столкнуться:SQUARE(a + b) расширяется до a + b * a + b, что не (a+b)*(a+b), а a + (b * a) + b.При необходимости при определении макросов следует позаботиться о добавлении круглых скобок вокруг элементов:#define SQUARE(X) ((X) * (X)) немного менее рискован.(Ян Кемп первым написал это в своем комментарии)
Вместо этого вы можете использовать встроенную функцию шаблона (не менее эффективную во время выполнения), подобную этой:
template <class T>
inline T square(T value)
{
return value*value;
}
Вы можете проверить, работает ли это:
int i = 2;
std::cout << square(++i) << " should be 9" << std::endl;
std::cout << square(++i) << " should be 16" << std::endl;
(не нужно писать
square<int>(++i)
потому что тип int является неявным для i)
Другие советы
Потому что макрос расширяется до:
++y * ++y
что приводит к неопределённому поведению в C++ - результат может быть чем угодно.Эта очень известная проблема должна быть описана в любом приличном учебнике по использованию макросов.Какой из них вы используете?
Поскольку макросы выполняют текстовую замену, поэтому написанный вами код расширяется до
printf("%d\n",++y * ++y );
и тогда порядок операций не определен, поэтому компилятор видит 2 приращения, а затем умножение
Поэтому будьте осторожны с макросами, лучше использовать функции, которые, поскольку компилятор может расширяться в строке, не будут требовать больше времени для запуска.
Во-вторых, не предполагайте, что произойдет, если вы увеличите и будете использовать переменные.
Макросы не являются функциями:они просто изменяют текст программы.Эта операция называется предварительная обработка и он автоматически выполняется перед компиляцией вашего кода.Люди пишут макросы, чтобы сэкономить время и внести некоторую вариативность в исходный код.
Когда ты пишешь SQUARE(x)
, фактического вызова функции не происходит, изменяется только текст.Операция довольно тупая, поэтому в таких случаях, как ваш, придется принимать дополнительные меры предосторожности.Обратитесь к другим ответам для объяснения вашего случая.