Что такое директивы препроцессора 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Что такое директивы препроцессора



Прежде чем приступить к компиляции программы, компилятор C++ запускает специальную программу, которая называется препроцессором. Препроцессор ищет в программе строки, начинающиеся с символа #, например #include или #define. Если препроцессор, например, встречает директиву #include, он включает указанный в ней файл в ваш исходный файл, как будто бы вы сами печатали содержимое включаемого файла в вашем исходном коде. Каждая программа, которую вы создали при изучении данной книги, использовала директиву #include, чтобы заставить препроцессор включить содержимое заголовочного файла iostream.h в ваш исходный файл. Если препроцессор встречает директиву #define, он создает именованную константу или макрокоманду. В дальнейшем, если препроцессор встречает имя константы или макрокоманды, он заменяет это имя значением, указанным в директиве #define.

Если вы определяете константы в своих программах, C++ не ограничивает вас в использовании только цифровых значений. Вы можете также использовать константы для хранения символьных строк и значений с плавающей точкой. Например, следующая программа BOOKINFO.CPP использует директиву # define для создания трех констант, которые содержат информацию об этой книге:

#include <iostream.h>

#define TITLE "Учимся программировать на языке C++"
#define LESSON 37
#define PRICE 22.95

void main(void)

{
cout << "Название книги: " << TITLE << endl;
cout << "Текущий урок: " << LESSON << endl;
cout << "Цена: $" << PRICE << endl;
}

Если вы откомпилируете и запустите эту программу, на экране дисплея появится следующий вывод:

С:\> BOOKINFO <ENTER>

Название книги: Учимся программировать на языке C++

Текущий урок: 37

Цена: $22.95

Использование #define для создания именованных констант

Для улучшения читаемости ваших программ заменяйте числовые значения в исходном коде константами со смысловыми именами. Для определения именованной константы ваши программы должны использовать директиву препроцессора #define. Размещайте свои константы в верхней части вашего исходного файла. Кроме того, чтобы отличать константы от переменных, большинство программистов для имен констант используют буквы верхнего регистра.

Например, следующая директива #define создает константу с именем SECONDS_PER_HOUR

#define SECONDS_PER_HOUR 3600

Во время компиляции программы препроцессор C++ будет заменять каждый экземпляр имени SECONDS_PER_HOUR числовым значением 3600. Обратите внимание, что определение константы не заканчивается точкой с запятой. Если вы поставите после 3600 точку с запятой, препроцессор C++ в дальнейшем заменит каждый экземпляр имени SECONDS_PER_HOUR его значением с точкой с запятой (3600;), что, очень вероятно, приведет к синтаксической ошибке.

ИСПОЛЬЗОВАНИЕ ИМЕНОВАННЫХ КОНСТАНТ ДЛЯ УПРОЩЕНИЯ ИЗМЕНЕНИЯ КОДА

Кроме того, что именованные константы делают вашу программу легче для восприятия, они еще и облегчают модификацию программ. Например, следующий фрагмент кода несколько раз ссылается на число 50 (количество студентов в классе):

#include <iostream.h>

void main(void)

{
int test_score8[50];
char grades[50];
int student;
for (student = 0; student < 50; student++) get_test_score(student);
for (student =0; student < 50; student++) calculate_grade(student);
for (student =0; student < 50; student++) print_grade(student);
}

Предположим, например, что количество студентов в классе увеличилось до 55. В этом случае вы должны отредактировать предыдущую программу, чтобы заменить каждый экземпляр значения 50 значением 55. В следующей программе применен другой подход, она использует именованную константу CLASS_SIZE:

#include <iostream.h>

#define CLASS_SIZE 50

void main(void)

{
int test_scores[CLASS_SIZE];
char grades[CLASS_SIZE];
int student;
for (student = 0; student < CLASS_SIZE; student++) get_test_score(student);
for (student = 0; student < CLASS_SIZE; student++) calculate_grade(student);
for (student = 0; student < CLASS_SIZE; student++) print_grade(student);
}

В данном случае для изменения количества студентов во всей программе вам необходимо изменить только одну строку, которая содержит директиву #define, определяющую эту константу:

#define CLASS_SIZE 55

ЗАМЕНА ВЫРАЖЕНИЙ МАКРОКОМАНДАМИ

Если ваши программы выполняют реальные вычисления, то в общем случае ваш код будет содержать сложные выражения типа:

result = (х*у-3) * (х*у-3) * (х*у-3);

В данном случае программа вычисляет куб выражения (х*у-3). Чтобы улучшить читаемость вашей программы и уменьшить вероятность внесения ошибок из-за опечаток, создайте макрокоманду с именем CUBE, которую ваша программа может использовать следующим образом:

result = CUBE(x*y-3);

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

Для создания макрокоманды вы должны использовать директиву препроцессора # define. Например, следующий оператор создает макрокоманду CUBE:

#define CUBE(x) ((х)*(х)*(х))

Как видите, программа определяет макрокоманду CUBE для умножения параметра х на самого себя дважды. Следующая программа SHOWCUBE.CPP использует макрокоманду CUBE для вывода куба значений от 1 до 10:

#include <iostream.h>

#define CUBE(x) ((x)* (x)* (x))

void main (void)

{
for (int i = 1; i <= 10; i++) cout << "Для " << i << " куб равен " << CUBE(i) << endl;
}

При компиляции этой программы препроцессор C++ заменит каждый экземпляр макрокоманды CUBE соответствующим определением. Другими словами, замена макрокоманды препроцессором приведет к следующему коду:

#include <iostream.h>

#define CUBE(x) ((х)*(х)*(х))
void main(void)

{
for (int i = 1; i <= 10; i++) cout << "Для " << i << " куб равен " << ((i) * (i) * (i)) << endl;
}

Обратите внимание, что предыдущая макрокоманда поместила параметр х внутрь круглых скобок, использовав запись ((х)*(х)*(х)) вместо (х*х*х). При создании макрокоманд вы должны помещать параметры в круглые скобки, как показано выше, тогда можете быть уверены, что C++ трактует ваши выражения именно так, как вы хотите. Как вы помните из урока 5, C++ использует старшинство операций для определения порядка выполнения арифметических операций. Предположим, например, что программа использует макрокоманду CUBE с выражением 3+5-2, как показано ниже:

result = CUBE(3+5-2);

Если макрокоманда заключает свой параметр в круглые скобки, то препроцессор сгенерирует следующий оператор:

result = ((3+5-2) * (3+5-2) * (3+5-2));

Однако, если в определении макрокоманды опустить круглые скобки, препроцессор сгенерирует следующий оператор:

result = (3+5-2*3+5-2*3+5-2);

Если вы вычислите оба выражения, то обнаружите, что их результаты отличаются. Заключая аргументы макрокоманды в круглые скобки, вы избавитесь от подобных ошибок.

ЧЕМ МАКРОКОМАНДЫ ОТЛИЧАЮТСЯ ОТ ФУНКЦИЙ

Определение макрокоманды не является функцией. Если программа использует функцию, то в выполняемую программу помещается только одна копия операторов функции. Каждый раз при вызове функции ваша программа помещает параметры в стек и затем выполняет переход к коду функции. После завершения функции программа удаляет параметры из стека и переходит обратно к оператору, который следует непосредственно за вызовом функции.

В случае с макрокомандой препроцессор заменяет в вашем коде каждую ссылку на макрокоманду соответствующим определением макрокоманды. Например, если предыдущая программа использует макрокоманду CUBE в 100 различных местах, препроцессор подставит код макрокоманды 100 раз. Используя макрокоманды, вы избегаете издержек на вызов функции (издержек на помещение параметров в стек и удаление их оттуда, а также издержек на выполнение перехода к коду функции и возврат из него). Это происходит благодаря тому, что в случае с макрокомандой препроцессор встраивает в тело программы соответствующие операторы. Однако, поскольку препроцессор заменяет каждую ссылку на макрокоманду соответствующим кодом, макрокоманды увеличивают размер вашей выполняемой программы.



Поделиться:


Последнее изменение этой страницы: 2016-09-13; просмотров: 169; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 13.59.82.167 (0.008 с.)