#c #c #macros
#c #c #макросы
Вопрос:
Какая макрокоманда может привести к неожиданным результатам?
#define YEAR_LENGTH 365
#define MONTH_LENGTH 30
#define DAYCALC(y, m, d) ((y * YEAR_LENGTH) (m * MONTH_LENGTH) d)
int main()
{
int x = 5, y = 4 , z = 1;
cout << DAYCALC(x *3 , y %3 , z) << endl ;
cout << DAYCALC(x 12 , y , 300) << endl ;
cout << DAYCALC(x , 40 - y , 3 z) << endl ;
cout << DAYCALC(x , y , (z 50)) << endl ;
cout << DAYCALC(x , y %3 , z) << endl ;
cout << DAYCALC(4 % x , y , z) << endl;
return 0;
}
Я запускаю программу очень хорошо без каких-либо неожиданных результатов.
Существуют ли какие-то скрытые исключения?
Комментарии:
1. Это вопрос домашнего задания? Это выглядит как один, но не помечено как один.
2. если это C , вы должны использовать встроенную функцию, а не макрос.
Ответ №1:
У вас проблема с предварением оператора. Макросы буквально разворачиваются как копирование и вставка текста.
Например:
DAYCALC(x , 40 - y , 3 z)
расширяется до:
((40 - y * YEAR_LENGTH) (x * MONTH_LENGTH) 3 z)
Обратите внимание, что 40 - y * YEAR_LENGTH
это не то, что вы хотите, из-за приоритета оператора.
Итак, вам нужно поместить ()
вокруг ваших параметров в макрос:
#define DAYCALC(y, m, d) (((y) * YEAR_LENGTH) ((m) * MONTH_LENGTH) (d))
В общем случае, если параметр макроса появляется в макрокоманде более одного раза, побочные эффекты, такие как y
(в вашем последнем операторе), также будут применены более одного раза. Так что с этим нужно быть осторожным.
Ответ №2:
вы можете проверить, что произойдет после расширения макроса с помощью g -E .
int main()
{
int x = 5, y = 4 , z = 1;
cout << ((x *3 * 365) (y %3 * 30) z) << endl ;
cout << ((x 12 * 365) (y * 30) 300) << endl ;
cout << ((x * 365) (40 - y * 30) 3 z) << endl ; //precedence problem
cout << ((x * 365) (y * 30) (z 50)) << endl ;
cout << ((x * 365) (y %3 * 30) z) << endl ;
cout << ((4 % x * 365) (y * 30) z) << endl;
return 0;
}
Ответ №3:
Вам нужно изменить DAYCALC;
#define DAYCALC(y, m, d) ( ((y) * YEAR_LENGTH) ((m) * MONTH_LENGTH) (d) )
Таким образом, если m, скажем, равно 3 z, то внутренний член будет правильным;
(3 z) * MONTH_LENGTH
неверный;
3 z*MONTH_LENGTH