Г. Шилдт - С#4.0 Полное руководство (1160795), страница 100
Текст из файла (страница 100)
Термин директива преироцессори появился в связи с тем, что подобные инструкции по традиции обрабатывались на отдельной стадии компиляции, называемой препроцессором. Обрабатывать директивы на отдельной стадии препроцессора в современных компиляторах уже не нужно, но само ее название закрепилось. Ниже приведены директивы препроцессора, определенные в С№. №е11№ №гте1тпе №е1зе №епг111 №еггог №11пе №епбгед1оп №цпаег №Ргадгла №гео1оп №нагп1пд Все директивы препроцессора начинаются со знака №. Кроме того, каждая директива препроцессора должна быть выделена в отдельную строку кода. Принимая во внимание современную объектно-ориентированную архитектуру языка С№, потребность в директивах препроцессора в нем не столь велика, как в языках программирования предыдущих поколений.
Тем не менее они могут быть иногда полезными, особенно для условной компиляции. В этом разделе все директивы препроцессора рассматриваются по очереди. Директива Иейле директива №Оейпе определяет последовательность символов, называемую идентпификаптором. Присутствие или отсутствие идентификатора может быль определено с помощью директивы №1 Т или № е11№ и поэтому используется для управления процессом компиляции. Ниже приведена общая форма директивы №стебпе.
№Оеггпе идентификатор Обратите внимание на отсутствие точки с запятой в конце этого оператора. Между директивой №оейпе и идентификатором может быть любое количество пробелов, но после самого идентификатора должен следовать только символ новой строки.
Так, для определения Идентификатора ЕХРЕЕ1МЕНТАЬ служит следующая директива. №че№1пе ЕХРЕЯтНЕНТАЬ ПРИМЕЧАНИЕ В с/с++ директива №оегтпе может использоваться для подстановки исходного текста, например для определения имени значения, а также для создания макрокоманд, похожих на функции. А в С№ такое применение директивы №Оейпе не поддерживается. В этом языке директива №бе№пе служит только для определения идентификатора. Директивы Ий и Вепрей Обе директивы, №1№ и №егн111, допускают условную компиляцию последовательности кода в зависимости от истинного результата вычисления выражения, включающего в себя один или несколько идентификаторов. Идентификатор считается истинным, если он определен, а иначе — ложным. Так, если идентификатор определен директивой №оетпте, то он будет оценен как истинный. Ниже приведена общая форма директивы № 1№.
530 Часть ). Язык С№ №11 идентификаторное выражение последовательность операторов №епг)11 Если идентификаторное выражение, следующее после директивы №11, истинно, то компилируется код (последовательность операторов), указываемый между ним и директивой №епс)11. В противном случае этот промежуточный код пропускается. Директива №епс(11 обозначает конец блока директивы №11.
Идентификаторное выражение может быль простым, как наименование идентификатора. В то же время в нем разрешается применение следующих операторов: !, ==, ! =, аз и ( ), а также круглых скобок. Ниже приведен пример применения упомянутых выше директив. Продемонстрировать применение директив №ЬГ, №епс11 и №г(е11пе. №Оетьпе ЕХРЕВТМЕМТА1. сагнэ Зувпеи; с1ава Тевг ( вгатьс яоьг) Ма1п() ( №11 ЕХРЕВ1МЕМТАЬ Сопво1е.игьгеЬЬпе("Компилируется для экспериментальной версии."); №епо11 Сопво1е.игьгеььпе (" Присутствует во всех версиях."); ) ) Этот код выдает следующий результат.
Компилируется для экспериментальной версии. Присутствует во всех версиях. В приведенном выше коде определяется идентификатор ехреВ1мехтйь. Поэтому когда в этом коде встречается директива №11, идентификаторное выражение вычисляется как истинное и затем компилируется первый оператор, содержащий вызов метода Х11геп№пе () . Если же удалить определение идентификатора ЕХРЕВТМЕХТАЬ и перекомпилировать данный код, то первый оператор, содержащий вызов метода Хг1 Се Ь1 не ( ), не будет охом пилирован, поскольку идентификаторное выражение директивы № 1 1 вычисляется как ложное.
Но второй оператор, содержащий вызов метода Хг1сеЬЬпе (), компилируется в любом случае, потому что он не входит в блок директивы №11. Как пояснялось выше, в директиве № 1 1 допускается указывать идентификаторное выражение. В качестве примера рассмотрим следующую программу. Использовать идентификаторное выражение. №г(е11пе ЕХРЕВ1МЕНТАЬ №Оегьпе ТВ1А). овьпд Зувгеач Глава 16. Пространства имен, препроцессор и сборки 531 с1авв тевс ( втат№с чотб Мати() ( №1№ ЕХРЕКТМЕИТАЬ Сопво1е.ит№оеЬтпе("Компилируется для экспериментальной версии.") №епб11 №1№ ЕХРЕК1МЕИТАЬ ЬЬ ТЕ1АЬ Сопво1е.вттот.нт1геЬ1пе("Проверка пробной экспериментальной версии."); №епб№Г Сопво1е.нгтпеЬгпе("Присутствует во всех версиях.") Зта программа дает следующий результат. Компилируется для экспериментальной версии.
Проверка пробной экспериментальной версии. Присутствует во всех версиях. В данном примере определены два идентификатора: ЕХРЕЕТМЕИТАЬ и ТЕТАЬ. Второй оператор, содержащий вызов метода Иг1беЬбпе (), компилируется лишь в том случае, если определены оба идентификатора. Для компилирования кода в том случае, если идентификатор не определен, можно воспользоваться оператором !, как в приведенном ниже примере. №1№ !ЕХРЕК1МБНТАЬ Сопво1е.ит11еЬ1пе("Этот код не экспериментальный!") №епб1№ Вызов метода будет скомпилирован только в том случае, если идентификатор ЕХРЕЕТМЕИТАЬ не определен.
Директивы $е1ве и $е1Ы Директива № е1ве действует аналогично условному оператору е1 ве языка С№, определяя альтернативный ход выполнения программы, если этого не может сделать директива №1№. С учетом директивы №е1ве предыдущий пример программы может быть расширен следующим образом. Продемонстрировать применение директивы №е1ве. №беттпе ЕХРЕА1МЕИТАЬ пегий Зувпеи; с1авв Тевг ( всаттс чо1б Мати() ( №11 ЕХРЕК1МЕНТА(, Сопво1е.нг11еьтпе("Компилируется для экспериментальной версии.") №е1ве Сопво1е.Ит1пеЬ1пе("Компилируется для окончательной версии.")у №епб1№ 532 Часть (.
Язык Сф №1№ ЕХРЕК1МЕМТйЬ ЬЬ ТП1АЬ Сопво1е.Едтог.нг1геЬЬпе("Проверка пробной экспериментальной версии.")," №е1ве Сопво1е.Едтог.Хх1сеьтпе("Это не пробная экспериментальная версия.") №епбг№ Сопво1е.иг№геЬЬпе("Присутствует во всех версиях.") ) Вот к какому результату приводит выполнение этой программы. Компилируется для экспериментальной версии. Это не пробная экспериментальная версия.
Присутствует во всех версиях. В данном примере идентификатор ТП1АЬ не определен, и поэтому часть №е1эе второй условной последовательности кода не компилируется. Обратите внимание на то, что директива №е1ее обозначает конец блока директивы №11 и в то же время — начало блока самой директивы №е1эе. Это необходимо потому, что с любой директивой №1 Т может быль связана только одна директива №епс(11. Более того, с любой директивой №11 может быть связана только одна директива №е1ве.
Обозначение №е11 1 означает "иначе если", а сама директива №е11 1 определяет последовательность условных операций 11-е1ее-11 для многовариантной компиляции. После директивы №е11 1 указывается идентификаторное выражение. Если это выражение истинно, то компилируется следующий далее кодовый блок, а остальные выражения директивы №е11 1 не проверяются. В противном случае проверяется следующий по порядку блок.
Если же ни одну из директив №е111 не удается выполнить, то при наличии директивы №е1эе выполняется последовательность кода, связанная с этой директивой, а иначе не компилируется ни один из кодовых блоков директивы №11. Ииже приведена общая форма директивы №е111. №ЬГ ндентнфикаторное выражение последовательность операторов №е111 идентнфнкаторное выражение последовательность операторов №е11№ идентнфикаторное выражение последовательность операторов №епб1№ В приведенном ниже примере демонстрируется применение директивы №е111.
Продемонстрировать применение директивы №е1х№. №Се№ьпе ЕЕЬЕАЯЕ овЬпэ Яувпегм с1авв Тевг вбагьс уоьб Наьп() ( Глава 16. Пространства имен, препроцессор и сборки 533 $11 ЕХРЕВ1МЕХТАЬ Сопзо1е.нгьсеЬЬпе("Компилируется для экспериментальной версии.") ()е111 АЕЬЕАЗЕ Сопво1е.нг1сешпе("Компилируется для окончательной версии."); ()е1ве Сопзо1е.нггсеььпе("Компилируется для внутреннего тестирования.") Еепбгс $11 ТВ1АЬ ьг !ЕЕЬЕАЯЕ Сспво1е.нггсевгпе("Пробная версия."); Фепбьг Сопяо1е.ХггсеШпе("Присутствует во всех версиях.") Этот код выдает следующий результат.
Компилируется для окончательной версии. присутствует во всех версиях. Директива $и11сьей С помощью директивы ()ппбеТ удаляется определенный ранее идентификатор. Это, по существу, означает, что он становится "неопределенным". Ниже приведена общая форма директивы () п обе Е. ()ппбет идентификатор рассмотрим следующий пример кода. ()бетгпе ЕМАЬЬ ()11 ЗМАЬЬ l! ()ппбег ЯМАЬЬ // теперь идентификатор БМАЬЬ не определен. После директивы ()ппбеГ идентификатор БМАЬЬ уже оказывается неопределенным. Директива ()побег применяется главным образом для локализации идентификаторов только в тех фрагментах кода, в которых они действительно требуются.