Программирование >>  Структурное программирование 

1 ... 299 300 301 [ 302 ] 303 304 305 ... 342


17.3. Директива препроцессора #define: символические константы

Директива препроцессора #define создает символические константы, обозначаемые идентификаторами, и макросы - операции, обозначаемые символьными строками. Формат директивы препроцессора #define следующий

tdefine идентификатор замещающий текст

После появления этой строки в файле все встретившиеся далее в тексте программы имена, совпавшие с элементом директивы идентификатор, будут автоматически заменены на указанный в директиве замещающий текст прежде, чем начнется компиляция программы. Например, после задания директивы

tdefine PI 3.14159

все последующие вхождения в текст программы символической константы PI будут заменены на численную константу 3.14159. Символические константы дают возможность программисту присвоить константе имя и использовать его далее в программе. Если возникнет необходимость изменить значение константы во всей программе, для этого достаточно будет внести только одно изменение в директиву препроцессора #define и перекомпилировать программу; значение

17.2. Директива препроцессора #include

Директива препроцессора #include уже использовалась в тексте этой книги. Директива #include применяется для включения копии указанного в директиве файла в то месте, где находится эта директива. Существуют две формы директивы #include:

tinclude <имя файла> tinclude имя файла

Различие между ними заключается в методе поиска препроцессором включаемого файла. Если имя файла заключено в угловые скобки (< и >), как это делается для включения заголовочных файлов стандартной библиотеки, то последовательность поиска препроцессором заданного файла в каталогах определяется используемой системой программирования; обычно просматривается заранее установленный список каталогов. Если имя файла заключено в кавычки, препроцессор сначала ищет файл в том каталоге, где находится компилируемый файл, а затем продолжает поиск тем же способом, что и при угловых скобках. Такой формой обычно пользуются для включения заголовочных файлов, определяемых программистом.

Директива #include обычно используется для включения стандартных заголовочных файлов, таких, как iostream.h и iomanip.h. Директива #include используется также при работе с программами, состоящими из нескольких исходных файлов, которые должны компилироваться вместе. Заголовочные файлы содержат объявления и определения, общие для различных программных файлов, и поэтому часто создаются и включаются в файлы программ. В качестве таких объявлений и определений выступают классы, структуры, объединения, перечислимые типы и прототипы функций.



константы будет изменено по всей программе автоматически. Отметьте: все, что находится справа от имени символической константы., является замещающим ее текстом. Например, после выполнения директивы #define PI =3.14159 препроцессор заменит все имена PI на текст =3.14159. Многие логические и синтаксические ошибки возникают по причине непонимания этого правила. Переопределение значения символической константы является также, обычным источником ошибок. Заметим, что в 0++ отдается предпочтение использованию именованных переменных типа const, а не символических констант. Константные переменные являются данными определенного типа и их имена видны отладчику. А если используется символическая константа, то после того, как символическая константа была заменена на соответствуюш;ий текст, только этот текст и будет виден отладчику. Недостатком переменных типа const является то, что им требуется память в объеме, соответствуюш;ем их типу, для хранения своего значения, тогда как для символических констант не требуется никакой дополнительной памяти.

Хороший стиль программирования 17.1

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

17.4. Директива препроцессора #define: макросы

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

Рассмотрим следуюш;ий макрос с одним параметром для расчета площади круга

#define CIRCLE AREA(х) ( PI * (х) * (х) )

Везде в файле, где появится идентификатор CIRCLE AREA(x), значение аргумента х будет использовано для замены х в замещающем тексте, символическая константа PI будет заменена ее значением (определенным выше) и этот расширенный текст макроса будет использован для замещения. Например, оператор с макросом в тексте программы

area = CIRCLE AREA{4);

примет вид:

area = ( 3.14159 * (4) * (4) ) ;

Поскольку это выражение состоит только из констант, его значение будет вычислено во время компиляции и полученный результат будет присвоен переменной area во время выполнения программы. Круглые скобки вокруг каждого включения параметра х в тексте макроса и вокруг всего выражения применяются для того, чтобы обеспечить соответствующий порядок вычис-



Вычисления, выполняемые макросом CIRCLE AREA, можно выполнять при помощи функции. Функция circle Area

double circleArea(double x) ( return 3.14159 * x * x; }

выполняет те же вычисления, что и макрос CIRCLE AREA. Недостатком использования этой функции является то, что на ее вызов должны быть затрачены некоторые ресурсы. Преимущества использования макроса CIR-CLE AREA состоят в том, что вычисления, выполняемые макросом, непосредственно помещаются в текст программы и не приводят к дополнительным накладным расходам, связанным с вызовом функции; при этом текст программы остается легко читаемым, потому что имя CIRCLE AREA говорит само за себя. Недостаток этого макроса в том, что значение аргумента вычисляется дважды. И конечно, макрос будет расширяться при каждом своем появлении в тексте программы. Если макрос большой, то это приводит к увеличению размера программы. Таким образом, нужно искать компромисс между быстродействием и размером программы (если у вас маленький диск). Заметим, что предпочтительнее использовать встраиваемые inline функции (см. главу 3), которые обеспечивают эффективность макросов и преимущества функций при разработке программного обеспечения.

Совет по повышению эффективности 17.1

Макросы могут использоваться для замены вызовов функций на встраиваемый в программу код. Это устраняет накладные расходы по вызову функции. Но предпочтительнее все же использовать встраиваемые функции.

лений в том случае, когда аргументом макроса является выражение. Например, при раскрытии макроса в операторе

area = CIRCLE AREA(с + 2);

оператор примет следующий вид:

area = ( 3.14159 * (с + 2) * (с + 2) );

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

area = 3.14159 * с + 2 * с + 2;

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

area = (3.14159 * с) + (2 * с) + 2; И будет получен неверный результат.

Типичная ошибка программирования 17.1

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



1 ... 299 300 301 [ 302 ] 303 304 305 ... 342

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика