История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...
Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...
Топ:
Определение места расположения распределительного центра: Фирма реализует продукцию на рынках сбыта и имеет постоянных поставщиков в разных регионах. Увеличение объема продаж...
Когда производится ограждение поезда, остановившегося на перегоне: Во всех случаях немедленно должно быть ограждено место препятствия для движения поездов на смежном пути двухпутного...
История развития методов оптимизации: теорема Куна-Таккера, метод Лагранжа, роль выпуклости в оптимизации...
Интересное:
Национальное богатство страны и его составляющие: для оценки элементов национального богатства используются...
Влияние предпринимательской среды на эффективное функционирование предприятия: Предпринимательская среда – это совокупность внешних и внутренних факторов, оказывающих влияние на функционирование фирмы...
Распространение рака на другие отдаленные от желудка органы: Характерных симптомов рака желудка не существует. Выраженные симптомы появляются, когда опухоль...
Дисциплины:
2019-10-30 | 165 |
5.00
из
|
Заказать работу |
|
|
Макроопределение может состоять только из имени макроса, например
# define MY_ H
После такой директивы считается, что макрос определен, но включать в текст программы макрокоманду MY_H нельзя – невозможно выполнить подстановку. Но имя макроса можно использовать в директивах условной трансляции, имеющих следующую структуру:
# ifndef <имя макроса>
<строки, которые включаются в компилируемый текст исходного модуля,
если макрос определен и исключаются из него, если макрос не определен>
# endif
Вместо условия #ifndef можно применять также противоположное ему условие # ifdef
Кроме директив #ifdef или #ifndef условная трансляция может задаваться служебным словом #if, после которого следует константное логическое выражение. В частности, директива
#if defined будет работать также, как #ifdef, а
#if!defined – также, как #ifndef.
Показанные выше директивы условной трансляции должны использоваться в любом заголовочном файле, чтобы не допустить его повторного включения в исходный модуль. Пусть у нас есть заголовочный файл My.h, в котором объявлены константа и прототип функции
const double _2Pi=2*3.14159;
void Func(int, int);
Если мы по ошибке включим его в программу дважды:
#include “My.h”
#include “My.h”
то получим сообщение error C2370: '_2 Pi': redefinition; different storage class о том, что в программе объявлены две константы с одинаковым именем. Вероятность возникновения такой ошибки достаточно велика из-за того, что включаемый файл допускает вложение в него других включаемых файлов. Если кроме My.h у нас создан еще List.h, внутри которого есть строка #include “My.h”, то уже вполне возможен повторный вызов My.h двумя строками
#include “My.h”
#include “List.h”
Eсловная трансляция позволяет исключить повторное включение в текст программы файла My_h:
|
#ifndef MY_H
#define MY_H
const double _2Pi=2*3.14159;
void Func(int, int);
# endif
При первом включении в текст программы файла My_h макрос MY_H еще не определен и компилятор обрабатывает строки файла. При втором, ниже по тексту, включении макрос определен и весь текст от #ifndef MY_H до #endif исключается из процесса компиляции.
Во время компиляции программы можно узнать, как она компилируется, как программа на языке Си или С++, или какая при компиляции была установлена модель памяти. Для этого можно проверить системные макросы: # ifdef _ cplusplus, # ifdef __ SMALL__ и пр.
Замечание. Описанными директивами можно проверить только наличие в программе макроопределений. Но проверить, объявлена ли переменная или константа с заданным именем нельзя. Включение в программу следующего фрагмента
Int MMM;
# ifdef MMM
int MM 1=3;
# endif
не приведет к объявлению переменной MM1, так как в программе нет макроса с именем MMM.
В приведенном примере условная трансляция позволяет включить или исключить часть текста из процесса компиляции. Если нужно выбрать один из двух вариантов, можно, аналогично условному оператору использовать ветвь #else. Директивы условной трансляции могут быть вложенными.
В качестве примера применения этих возможностей рассмотрим, как в С++ для MS DOS определена константа NULL.
Указатели в С++, работающем в среде DOS, могут состоять из двух или четырех байтов в зависимости от модели памяти. Поэтому, например, в модели HUGE для совместимости с указателем константа NULL должна быть длинным целым, а в модели SMALL – словом. Для настройки на модель памяти эта константа в среде Borland определена в файле NULL.h следующим образом
#ifndef NULL
#if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
# define NULL 0 Если модель крохотная, малая или средняя NULL – это слово.
# else
# define NULL 0 L Для других моделей это двойное слово.
# endif Это #endif для вложенной директивы #if defined.
# endif Это #endif для директивы #ifndef NULL.
Итак, если константа NULL уже определена раньше, препроцессор ничего не вставит в текст программы, если нет, он вставит строку
|
define NULL 0
или строку
define NULL 0L.
В результате такого определения в языке С++ появляется некоторая нелогичность, которую не очень рекламируют: указатели не совместимы с целыми, но число ноль можно записать в указатель, а значение указателя NULL – в переменную целого типа.
Но сделанное для нуля исключение того стоит, в результате все синтаксические конструкции работают с пустым указателем, как с обычным нулем. Вспомним, как мы проверяли, открылся ли файл:
if ((f = fopen (“ txt. txt ”,” w ”))! = NULL) …
потому что в скобках должно быть целое число. Теперь ясно, что можно было проверять и значение указателя f:
if (f=fopen (“txt.txt”,”w”))...
При знакомстве со списками мы видели, как это свойство пустого указателя позволяет просматривать списки циклом for.
В среде Windows указатели всегда 32-битные, используется только одна модель памяти, поэтому аналогичное определение в файле Windef.h выглядит значительно проще:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
Директивы условной трансляции позволяют также выбрать для компиляции один из нескольких вариантов текста при помощи следующей конструкции
# if <условие 1>
<Текст, используемый при выполнении условия 1>
# elif < условие 2>
< Текст, используемый при выполнении условия 2>
# elif < условие n>
< Текст, используемый при выполнении условия n >
# else
< Этот текст компилятор использует, если не выполнено ни дно из условий>
# endif
Следует обратить внимание на отличие условной компиляции от условного оператора:
– в условном операторе обе ветви присутствуют в исполняемом файле, но выполняется только одна;
– при условной компиляции в исполнительном модуле только одна выбранная ветвь. Это уменьшает размер файла и увеличивает скорость, так как во время работы программы не выполняется проверка условий – они проверены на этапе компиляции.
|
|
Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...
Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...
Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначенные для поддерживания проводов на необходимой высоте над землей, водой...
Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!