Читать «C++: базовый курс» онлайн - страница 329
Herbert Schildt
using namespace std;
#define EVEN(a) a%2==0 ? 1 : 0
int main()
{
if(EVEN(9+1)) cout << "четное число";
else cout << "нечетное число ";
return 0;
}
Эта программа не будет работать корректно, поскольку не обеспечена правильная подстановка значений. При компиляции выражение EVEN(9+1) будет заменено следующим образом.
9+1%2==0 ? 1 : 0
Напомню, что оператор "%" имеет более высокий приоритет, чем оператор "+". Это значит, что сначала выполнится операция деления по модулю (%) для числа 1, а затем ее результат будет сложен с числом 9, что (конечно же) не равно 0. Чтобы исправить ошибку, достаточно заключить в круглые скобки аргумент a в макроопределении EVEN, как показано в следующей (исправленной) версии той же программы.
// Эта программа работает корректно.
#include <iostream>
using namespace std;
#define EVEN(a) (a)%2==0 ? 1 : 0
int main()
{
if(EVEN(9+1)) cout << "четное число";
else cout << "нечетное число";
return 0;
}
Теперь сумма 9+1 вычисляется до выполнения операции деления по модулю. В общем случае лучше всегда заключать параметры макроопределения в круглые скобки, чтобы избежать непредвиденных результатов, подобных описанному выше.
Использование макроопределений вместо настоящих функций имеет одно существенное достоинство: поскольку код макроопределения расширяется в строке, и нет никаких затрат системных ресурсов на вызов функции, скорость работы вашей программы будет выше по сравнению с применением обычной функции. Но повышение скорости является платой за увеличение размера программы (из-за дублирования кода функции).
Важно! Несмотря на то что макроопределения все еще встречаются в C++-коде, макросы, действующие подобно функциям, можно заменить спецификатором inline, который справляется с той же ролью лучше и безопаснее. (Вспомните: спецификатор inline обеспечивает вместо вызова функции расширение ее тела в строке.) Кроме того, inline-функции не требуют дополнительных круглых скобок, без которых не могут обойтись макроопределения. Однако макросы, действующие подобно функциям, все еще остаются частью С++-программ, поскольку многие С/С++-программисты продолжают использовать их по привычке.
Директива #еrror
Директива #error отображает сообщение об ошибке.
Директива #error дает указание компилятору остановить компиляцию. Она используется в основном для отладки. Общий формат ее записи таков.
#error сообщение
Обратите внимание на то, что элемент сообщение не заключен в двойные кавычки. При встрече с директивой #error отображается заданное сообщение и другая информация (она зависит от конкретной реализации рабочей среды), после чего компиляция прекращается. Чтобы узнать, какую информацию отображает в этом случае компилятор, достаточно провести эксперимент.
Директива #include
Директива #include включает заголовок или другой исходный файл.
Директива препроцессора #include обязывает компилятор включить либо стандартный заголовок, либо другой исходный файл, имя которого указано в директиве #include. Имя стандартных заголовков заключается в угловые скобки, как показано в примерах, приведенных в этой книге. Например, эта директива