Типы оградительных сооружений в морском порту: По расположению оградительных сооружений в плане различают волноломы, обе оконечности...
История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...
Топ:
Когда производится ограждение поезда, остановившегося на перегоне: Во всех случаях немедленно должно быть ограждено место препятствия для движения поездов на смежном пути двухпутного...
Генеалогическое древо Султанов Османской империи: Османские правители, вначале, будучи еще бейлербеями Анатолии, женились на дочерях византийских императоров...
Комплексной системы оценки состояния охраны труда на производственном объекте (КСОТ-П): Цели и задачи Комплексной системы оценки состояния охраны труда и определению факторов рисков по охране труда...
Интересное:
Как мы говорим и как мы слушаем: общение можно сравнить с огромным зонтиком, под которым скрыто все...
Инженерная защита территорий, зданий и сооружений от опасных геологических процессов: Изучение оползневых явлений, оценка устойчивости склонов и проектирование противооползневых сооружений — актуальнейшие задачи, стоящие перед отечественными...
Что нужно делать при лейкемии: Прежде всего, необходимо выяснить, не страдаете ли вы каким-либо душевным недугом...
Дисциплины:
2019-10-30 | 167 |
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
Следует обратить внимание на отличие условной компиляции от условного оператора:
– в условном операторе обе ветви присутствуют в исполняемом файле, но выполняется только одна;
– при условной компиляции в исполнительном модуле только одна выбранная ветвь. Это уменьшает размер файла и увеличивает скорость, так как во время работы программы не выполняется проверка условий – они проверены на этапе компиляции.
|
|
История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...
Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...
Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...
Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!