(PI*(r)* (r))
7:
|
#define
|
MAX (a, b) (((a)
|
> (b) ) ? (a) : (b) )
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
int main()
1 1 :
|
{
|
1 2 :
|
cout « "Enter an integer: ";
|
int Inputl = 0;
cin » Inputl;
16:
|
cout
|
«
|
"SQUARE(" « Input1 «
|
")="
|
«
|
SQUARE(Input1) «
|
endl;
|
17:
|
cout
|
«
|
"Area of a circle with
|
radius
|
" «
|
Inputl « " is:
|
|
cout « AREA_CIRCLE(Inputl) « endl;
cout « "Enter another integer: ";
int Input2 = 0;
cin » Input2;
23:
24: cout « "MIN(" « Inputl « ", " « Input2 « ") = ";
cout « MIN (Inputl, Input2) « endl;
27: cout « "MAX(" « Inputl « ", " « Input2 « ") = ";
cout « MAX (Inputl, Input2) « endl;
return 0;
}
Результат
Enter an integer: 36
SQUARE(36) = 1296
Area of a circle with radius 36 is: 4071.51
Enter another integer: -101
MIN(36, -101) = -101
MAX(36, -101) = 36
Использование директивы #define для написания макрофункции
|
357
|
Анализ
Строки 4-8 содержат несколько вспомогательных макрофункций, которые возвращают квадрат числа, площадь круга, а также наибольшее и наименьшее из двух чисел. Обратите внимание, что функция AREA C IR C L E в строке 6 вычисляет площадь, использует констан ту P I, свидетельствуя таким образом, что один макрос может многократно использовать другой. В конце концов, это только команды препроцессора для простой замены оного текста другим. Давайте проанализируем строку 25, где используется макрофункция MIN:
cout « MIN (Inputl, Input2) « endl;
После разворачивания макроса по месту эта строка, по существу, передается компиля тору в следующем виде:
cout « (((Inputl) < (Input2)) ? (Inputl) : (Input2)) « endl;
ВНИМАНИЕ! Макрофункции не учитывают тип, а следовательно, могут быть опасны.
Например, макрофункция A R E A _C I R C L E должна в идеале возвращать тип
double, чтобы вы были уверенны в точности возвращаемого значения вычис
ленной площади и ее независимости от характера введенного радиуса.
Зачем все эти скобки?
Снова обратите внимание на макрос вычисления площади круга:
#define AREA_CIRCLE(г) (PI*(г)* (г))
этого вычисления странный синтаксис с множеством скобок. Сравните его с функ цией A r e a () из листинга 7.1 занятия 7, “Организация кода при помощи функций” .
Определения функций (реализации)
double Area(double InputRadius)
{
return Pi * InputRadius * InputRadius; // видите, никаких скобок
}
Так почему же для макроса мы переусердствовали со скобками, когда та же формула в функции значительно отличается? Причина в способе, которым препроцессор обрабаты вает макрос, т.е. в механизме текстовой подстановки.
Рассмотрим макрос без множества скобок:
#define AREA_CIRCLE(г) (PI*r*r)
Что будет при вызове этого макроса в таком выражении:
cout « AREA_CIRCLE (4+6);
Он был бы развернут препроцессором в такой код:
cout « (Р1*4+6*4 + 6) ; // совсем не то, что и Р1*10*10
Таким образом, по правилам приоритета операций, согласно которым умножение вы полняется до сложения, компилятор фактически вычисляет площадь так:
cout « (Р1*4+24+6); // 42.5664 (что явно неправильно)
358 ЗАНЯТИЕ 14. Макросы и шаблоны
Без круглых скобок преобразование текста привело к искажению логики программы!
Применение круглых скобок позволяет избежать этой проблемы:
#define AREA_CIRCLE(г) (PI*(г)* (г))
cout « AREA_CIRCLE (4+ 6);
Выражение после подстановки воспринимается компилятором как следующее:
cout « (PI*(4+6)*(4+6)); // Р1*10*10, как и ожидалось
Скобки автоматически обеспечивают правильное вычисление площади, делая код ма кроса независимым от приоритета операторов.
Использование макроса assert для проверки выражений
Хотя, конечно, принято просматривать и проверять каждый путь выполнения кода не посредственно после его написания, это зачастую оказывается физически невозможно. Но можно вставить в код проверки, которые проверяют значения выражений или пере менных.
акрос a s s e r t позволяет сделать именно это. Чтобы использовать макрос a s s e r t , необходимо включить заголовок a s s e r t . h, а синтаксис его использования следующий:
Do'stlaringiz bilan baham: |