circ = pi * diameter;
а позже компилятор подставил бы в него фактическое значение константы.
В чем достоинства такого метода?
Во-первых, имя говорит нам больше, чем число. Сравним два оператора
owed = 0 015 * housevl, owed = taxrate * housevl;
Если мы изучаем большую программу, то второй вариант будет нам более понятен.
Во-вторых, предположим, что некоторая константа использовалась в нескольких местах программы и впоследствии возникла необходимость изменить ее значение - ведь в конце концов и налоговые тарифы (taxrate) меняются, и, к примеру, некое законодательное собрание приняло однажды закон впредь считать число p равным 31/7. (Весьма вероятно, что окружности пришлось при этом скрываться от правосудия). В таком случае требуется только изменить определение символической константы, а не отыскивать каждый случай ее появления в программе.
Теперь осталось выяснить, как можно создать такую символическую константу? Первый способ заключается в том, чтобы описать некоторую переменную и положить ее равной требуемой константе.
Мы могли бы сделать это следующим образом
float taxrate, taxrate = 0 015;
Такой способ подходит для небольшой программы, в других же случаях он несколько неэкономичен, поскольку каждый раз при использовании переменной taxrate компьютер должен будет обращаться к той ячейке памяти, которая отведена данной переменной. Это служит примером подстановки "во время выполнения", так как она производится именно при выполнении программы. К счастъю, в языке Си имеется и другой, лучший способ.
Этот способ реализуется с помощью препроцессора языка Си. В гл. 2 мы уже видели, как препроцессор использует директиву #include для включения информации из другого файла в программу. Кроме того, препроцессор дает нам возможность задавать константы. Для этого в начало файла, содержащего вашу программу, необходимо добавить только одну строку, аналогичную следующей:
#define TAXRATE 0.015
При компиляции программы каждый раз, когда появится переменная TAXRATE, она будет заменяться величиной 0.015. Это называется подстановкой "во время компиляции". К тому моменту, когда вы начнете выполнение своей программы, все подстановки будут уже сделаны.
Несколько замечаний по поводу формата.
#defineTAXRATEПриведем простой пример:
/* пицца */
#define PI 3,14159
main( ) /* изучение вашей пиццы */
{
float area, circum, radius;
printf("Чемy равен радиус вашей пиццы? \n");
scanf("%f", &radius);
area = PI * radius * radius;
printf(" Основные параметры вашей пиццы следующие \n");
printf(" длина окружности = %1.2f, площадь =%1.2f \n circum, area);
}
РИС.4.5. Обработка текста программы препроцессором
Использование спецификации %1.2f в операторе printf( ) приведет к тому, что при печати результаты будут округлены до двух десятичных цифр. Мы понимаем, конечно, что написанная выше программа может и не отражать ваши собственные вкусы, касающиеся пиццы, но во множестве программ, посвященных этому вопросу, она займет свое скромное место. Вот один из примеров ее выполнения:
Чему равен радиус вашей пиццы? 6.0
Основные параметры вашей пиццы следующие: длина окружности = 37.70,
площадь окружности = 113.40.
Директиву #define можно также использовать для определения символьных и строковых констант. Необходимо использовать знак "апостроф" в первом случае и кавычки - во
втором. Примеры, приведенные ниже, вполне правомерны
#define ВЕЕР '\007'
#define ESS 'S'
#deline NULL '\0'
#define OOPS "Ну вот, вы и сделали это!"
А теперь мы хотим обрадовать лентяев. Предположим, вы разрабатываете целый пакет программ, использующих один и тот же набор констант. Вы можете произвести следующие действия:
1. Соберите все ваши директивы #define в один файл и назовите его, например, const.h.
2. В начало каждого файла, содержащего программу, включите директиву #include "const.h."
Тогда, если вы будете выполнять программу, препроцессор прочтет файл с именем const.h и использует все директивы #define вашей программы. Получилось так, что символ .h в конце имени файла напомнит вам, что этот файл является "заголовком", т.е. в нем содержится вся информация, которая должна попасть в начало вашей программы. Самому препроцессору безразлично, используете ли вы символ .h в имени файла или нет.
Язык Си - искусный фокусник: создание псевдоимен
#define#include "alias. h"
program begin
whole yours, mine then
spitout(" Введите, пожалуйста, целое число.\n" )
then takem(" %d", & yours)
then mine = yours times TWO then
spitout(" %d в два раза больше вашего числа! \n" , mine) then end
Странно, текст что-то смутно напоминает, язык немного похож на Паскаль, но программа не похожа на Си-программу. Секрет лежит, конечно, в файле с именем alias.h. Давайте посмотрим, что в нем содержится?
alias. h #define program main( )
#define degin { #define enf } #define then;
#define takein scanf
#define spilout printf
#define TWO 2
#define times *
#define whole int
Этот пример иллюстрирует, как работает препроцессор. Он просматривает вашу программу и проводит поиск элементов, определяемых директивами #define. Обнаружив такие элементы, он полностью заменяет их. В нашем примере во время компиляции все слова then заменяются символами "точка с запятой", end - } и т.д. Результирующая программа будет полностью идентична той, которую мы могли бы получить, если бы с самого начала писали ее в обычных терминах языка Си.