C++. Условная компиляция. Директивы #if, #else, #elif, #endif, #ifdef, #ifndef. Оператор defined

Условная компиляция. Директивы #if, #else, #elif, #endif, #ifdef, #ifndef. Оператор defined


Содержание


1. Директивы #if, #else, #elif, #endif. Условная компиляция
1.1. Комбинация директив #if — #endif

С помощью директив #if, #else, #elif, #endif можно задать части программы, которые нужно откомпилировать в зависимости от значения константного выражения.

Общая форма директивы #if следующая

#if constant_expression
  operators_sequence
#endif

здесь

  • constant_expression – константное выражение, возвращающее true или false;
  • operator_sequence – последовательность операторов, выполняемая если constant_expression=true.

Пример.

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 2

// Число Пі
#define Pi 3.1415926535

// Если решение равно 1, то вычислить длину окружности
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius
#endif

// Если решение равно 2, то вычислить площадь круга
#if N_SOLUTION == 2
#define RESULT(radius) Pi*radius*radius
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычислить площадь круга
  double area = RESULT(r);
  cout << "area = " << area << endl;
}

Результат выполнения программы

r = 3
area = 28.2743
 
1.2. Комбинация директив #if — #else — #endif

Директивы #if – #else – #endif позволяют откомпилировать одну из двух частей программы в зависимости от значения условного выражения. Общая форма использования данной директивы следующая:

#if consant_expression
  operators_sequence_1
#else
  operators_sequence_2
#endif

здесь

  • constant_expression – выражение, возвращающее значение логического типа (true или false);
  • operators_sequence_1 – последовательность операторов, которую нужно выполнить, если constant_expression=true;
  • operators_sequence_2 – последовательность операторов, которую нужно выполнить, если constant_expression=false.

Пример.

В примере в зависимости от значения N_SOLUTION компилируется нужный фрагмент кода, определяющий длину окружности или площадь круга.

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 1

// Число Пі
#define Pi 3.1415926535

// Если решение равно 1, то компилируется фрагмент, который вычисляет длину окружности,
// иначе компилируется фрагмент вычисляющий площадь окружности.
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius
#else
#define RESULT(radius) Pi*radius*radius
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычисление
  double result = RESULT(r);
  cout << "result = " << result << endl;
}

Результат

r = 3
result = 18.8496
 
1.3. Комбинация директив #if — #elif — #endif. Цепочка if-else-if

Комбинация директив #if-#elif-#endif образует так называемую цепочку if-else-if или ступенчатую (каскадную) форму директивы #if. Директива #elif расшифровывается как else-if. С помощью данной формы директив можно делать проверку многих условий. Общий вид директивы #if-#elif-#endif следующий

#if expression_1
  operators_sequence_1
#elif expression_2
  operators_sequence_2
...
#elif expression_N
  operators_sequence_N
#endif

здесь

  • expression_1, expression_2, expression_N – некоторое выражение, которое может бать истинно (true) или не истинно (false);
  • operators_sequence_1, operators_sequence_2, operators_sequence_N – последовательность операторов, которые нужно откомпилировать в соответствующем блоке кода.

Пример.

В примере, в зависимости от значения N_SOLUTION вычисляется соответствующая формула

#include <iostream>
using namespace std;

// Номер решения
#define N_SOLUTION 3

// Число Пі
#define Pi 3.1415926535

// Компилируется фрагмент, который соответствует номеру номеру решения.
#if N_SOLUTION == 1
#define RESULT(radius) 2*Pi*radius // длина окружности
#elif N_SOLUTION == 2
#define RESULT(radius) Pi*radius*radius // площадь круга
#elif N_SOLUTION == 3
#define RESULT(radius) 4.0/3*Pi*radius*radius*radius // объем шара
#endif

void main()
{
  // 1. Радиус
  double r;

  // 2. Ввести радиус окружности
  cout << "r = ";
  cin >> r;

  // 3. Вычисление
  double result = RESULT(r);
  cout << "result = " << result << endl;
}

Результат

r = 3
result = 113.097
 
2. Директивы #ifdef, #ifndef. Условная компиляция

Директивы #ifdef и #ifndef обеспечивают еще один вид условной компиляции. Дословно значение директив можно определить следующим образом: «if defined» (если определено), «if not defined» (если не определено).

Общий вид директив #ifdef:

#ifdef macros_name
  operators_sequence
#endif

здесь

  • macros_name – имя макроса, которое проверяется на то, определено ли оно оператором #define. Если имя макроса определено, выполняется последовательность operators_sequence;
  • operators_sequence – некоторая последовательность.

Общий вид директивы #ifndef:

#ifndef macros_name
  operators_sequence
#endif

здесь

  • macros_name – имя макроса, которое может быть определено или не определено. Если имя макроса определено директивой #define, то последовательность operator_sequence не выполняется;
  • operators_sequence – последовательность операторов.

Пример.

#include <iostream>
using namespace std;

#define Is_Calc_Length // Нужно ли определять макрос Length?

// Если нужно определить макрос, вычисляющий расстояние
// между двумя точками, то определить его
#ifdef Is_Calc_Length
#define Length(x1, y1, x2, y2) sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
#endif

// Если не нужно определять макрос Length, то вернуть 0
#ifndef Is_Calc_Length
#define Length(x1, y1, x2, y2) 0
#endif

void main()
{
  double x1, y1, x2, y2;
  cout << "x1 = "; cin >> x1;
  cout << "y1 = "; cin >> y1;
  cout << "x2 = "; cin >> x2;
  cout << "y2 = "; cin >> y2;

  double len = Length(x1, y1, x2, y2);
  cout << "len = " << len << endl;
}

Результат

x1 = 1
y1 = 2
x2 = 3
y2 = 5
len = 3.60555
 
3. Оператор defined. Определение, существует ли в программе макроимя

Оператор defined используется в сочетании с директивой #if. Сочетание этих двух элементов заменяет директиву #ifdef. Общая форма использования оператора defined имеет вид

defined macros_name

здесь

  • macros_name – имя макроса, которое проверяется на наличие.

Пример.

В примере демонстрируется оригинальный способ решений вычисления квадратного уравнения на основе предопределенных формул.

#include <iostream>
using namespace std;

// Оператор defined.
// Формули вычисления квадратного уравнения.
#define D(a, b, c) (b*b - 4*a*c)
#define X1(a, b, c) ((-b - sqrt(D(a,b,c))) / (2*a))
#define X2(a, b, c) ((-b + sqrt(D(a,b,c))) / (2*a))

void main()
{
  // Вычисление квадратного уравнения.
  // Проверка, есть ли формулы вычисления квадратного уравнения.
#if defined D
#if defined X1
#if defined X2
  // 1. Объявить переменные
  double a, b, c;

  // 2. Ввести коэффициенты
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;
  cout << "c = "; cin >> c;

  // 3. Проверка, существует ли уравнение
  if (a == 0)
  {
    cout << "Incorrect value of a (a==0)." << endl;
    return;
  }

  // 4. Если дискриминант больше или равен 0, то произвести вычисление
  if (D(a, b, c) >= 0)
  {
    cout << "x1 = " << X1(a, b, c) << endl;
    cout << "x2 = " << X2(a, b, c) << endl;
  }
  else
    cout << "The equation has no roots." << endl;

#endif
#endif
#endif
}

Результат

a = -3
b = -4
c = 5
x1 = 0.7863
x2 = -2.11963
 

Связанные темы