некоторые макрокоманды могут иметь неожиданные результаты в C ?

#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 , вы должны использовать встроенную функцию, а не макрос.

3. github.com/Keith-S-Thompson/42

Ответ №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