8-900-374-94-44
[email protected]
Slide Image
Меню

Директива define c: Директивы препроцессора: #define, директивы условной компиляции

Содержание

Директива #define. Язык программирования Си для персонального компьютера

Директива #define

Синтаксис:

#define <идентификатор> <текст>

#define <идентификатор> <список параметров> <текст>

Директива #define заменяет все вхождения <идентификатора> в исходном файле на <текст>, следующий в директиве за <идентификатором>. Этот процесс называется макроподстановкой, <идентификатор> заменяется лишь в том случае, если он представляет собой отдельную лексему. Например, если <идентификатор> является частью строки или более длинного идентификатора, он не заменяется. Если за <идентификатором> следует <список параметров>, то директива определяет макроопределение с аргументами.

<Текст> представляет собой набор лексем, таких как ключевые слова, константы, идентификаторы или выражения.

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

<Текст> может быть опущен. В этом случае все экземпляры <идентификатора> будут удалены из исходного текста программы. Тем не менее, сам <идентификатор> рассматривается как определенный и при проверке директивой #if дает значение 1 (смотри раздел 7.4.1).

<Список параметров>, если он задан, содержит один или более идентификаторов, разделенных запятыми. Идентификаторы в списке должны отличаться друг от друга. Их область действия ограничена макроопределением, в котором они заданы. Список должен быть заключен в круглые скобки. Имена формальных параметров в <

тексте> отмечают позиции, в которые должны быть подставлены фактические аргументы макровызова. Каждое имя формального параметра может появиться в <тексте> произвольное число раз.

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

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

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

Внутрь <текста> в директиве #define могут быть вложены имена других макроопределений или констант. Их расширение производится лишь при расширении <идентификатора> этого <текста>, а не при его определении директивой #define. Это надо учитывать, в частности, при взаимодействии вложенных именованных констант и макроопределений с директивой #undef: к моменту расширения содержащего их текста они могут уже оказаться отменены директивой

#undef.

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

#define х х

не приведет к зацикливанию препроцессора.

Примеры.

/* пример 1 */

#define WIDTH 80

#define LENGTH (WIDTH + 10)

/* пример 2 */

#define FILEMESSAGE «Попытка создать файл

не удалась из-за нехватки дискового пространства»

/* пример 3 */

#define REG1 register

#define REG2 register

#define REG3

/* пример 4 */

#define MAX(x, y)((x)>(у)) ? (x) : (у)

/* пример 5 */

#define MULT(a, b) ((a)*(b))

В первом примере идентификатор WIDTH определяется как целая константа со значением 80, а идентификатор LENGTH — как текст (WIDTH + 10).

Каждое вхождение идентификатора LENGTH в исходный файл будет заменено на текст (WIDTH + 10), который после расширения идентификатора WIDTH превратится в выражение (80 + 10). Скобки, окружающие текст (WIDTH + 10), позволяют избежать ошибок в операторах, подобных следующему:

var = LENGTH * 20;

После обработки препроцессором оператор примет вид:

var = (80 + 10)* 20;

Значение, которое присваивается var, равно 1800. В отсутствие скобок в макроопределении оператор имел бы следующий вид:

var = 80 + 10*20;

Значение var равнялось бы 280, поскольку операция умножения имеет более высокий приоритет, чем операция сложения.

Во втором примере определяется идентификатор FILEMESSAGE. Его определение продолжается на вторую строку путем использования символа обратный слэш непосредственно перед нажатием клавиши ENTER.

В третьем примере определены три идентификатора, REG1, REG2, REG3. Идентификаторы REG1 и REG2 определены как ключевые слова

register. Определение REG3 опущено и, таким образом, любое вхождение REG3 будет удалено из исходного файла. В разделе 7.4.1 приведен пример, показывающий, как эти директивы могут быть использованы для задания класса памяти register наиболее важным переменным программы.

В четвертом примере определяется макроопределение МАХ. Каждое вхождение идентификатора МАХ в исходном файле заменяется на выражение ((x)>(у))?(x):(у), в котором вместо формальных параметров х и у подставлены фактические. Например, макровызов

МАХ(1,2)

заменится на выражение

((1)>(2))?(1):(2)

а макровызов

MAX(i, s[i])

заменится на выражение

((i)>(s(i]))?(i):(s(i])

Обратите внимание на то, что в этом макроопределении аргументы с побочными эффектами могут привести к неверным результатам. Например, макровызов

MAX(i, s[i++])

заменится на выражение

((i)>(s[i++]))?(i):(s[i++])

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

В пятом примере определяется макроопределение MULT. Макровызов MULT(3,5) в тексте программы заменяется на (3)*(5). Круглые скобки, в которые заключаются фактические аргументы, необходимы в тех случаях, когда аргументы макроопределения являются сложными выражениями. Например, макровызов

MULT(3+4,5+6)

заменится на (3+4)*(5+6), что равняется 76. В отсутствие скобок результат подстановки 3+4*5+6 был бы равен 29.

Новая директива, начинающаяся с точки

Новая директива, начинающаяся с точки .MODEL &lt;имя&gt; &lt;тип&gt; ([&lt;имя параметра&gt; = &lt;значение&gt;]*)Например, запись.MODEL KT coreвводит модель для связанных катушек индуктивности, имя должно начинаться с K. Если команда также содержит слово core, то используется нелинейная модель.

4. Опережающие описания и подключение подпрограмм. Директива

4. Опережающие описания и подключение подпрограмм. Директива В программе может содержаться несколько подпрограмм, т. е. структура программы может быть усложнена. Однако эти подпрограммы могут располагаться на одном уровне вложенности, поэтому сначала должно идти

R.16.9 Пустая директива

R.16.9 Пустая директива Команда препроцессора вида#не оказывает никакого

Правило 2: Предпочитайте const, enum и inline использованию #define

Правило 2: Предпочитайте const, enum и inline использованию #define Это правило лучше было бы назвать «Компилятор предпочтительнее препроцессора», поскольку #define зачастую вообще не относят к языку C++. В этом и заключается проблема. Рассмотрим простой пример; попробуйте написать

Директива .maxstack

Директива .maxstack При реализации метода непосредственно средствами CIL нужно помнить о специальной директиве, которая называется .maxstack. Как следует из ее названия, директива .maxstack задает максимальное число переменных, которые может вместить стек в любой момент времени при

4. Символьные строки директива #define, функции printf( ) и scanf( ) 

4. Символьные строки директива #define, функции printf( ) и scanf( )    В этой главе мы продолжим нашу «игру» с данными покопаемся в вопросах, выходящих за пределы тех, которые были связаны с типами данных, и рассмотрим символьную строку Сначала опи шем важное средство языка —

ДИРЕКТИВЫ ПРЕПРОЦЕССОРА #define, #include, #undef, #if, #ifdef, #ifndef, #else, #endif

ДИРЕКТИВЫ ПРЕПРОЦЕССОРА #define, #include, #undef, #if, #ifdef, #ifndef, #else, #endif      Язык Си был разработан в помощь работающим программистам, а им нравится его препроцессор. Этот полезный помощник просматривает программу до компилятора (отсюда и термин «препроцессор») и заменяет

Директива #undef

Директива #undef Синтаксис:#undef &lt;идентификатор&gt;Директива #undef отменяет действие текущего определения #define для &lt;идентификатора&gt;. Чтобы отменить макроопределение посредством директивы #undef, достаточно задать его &lt;идентификатор&gt;. Задание списка параметров не

Директива обработки ошибок

Директива обработки ошибок В СП ТС реализована директива #error. Ее формат:#error &lt;текст&gt;Обычно эту директиву записывают среди директив условной компиляции для обнаружения некоторой недопустимой ситуации. По директиве #error препроцессор прерывает компиляцию и выдает

Пустая директива

Пустая директива Для повышения читабельности программ СП ТС распознает пустую директиву, состоящую из строки, содержащей просто знак #. Эта директива всегда

3.12. Директива typedef

3.12. Директива typedef Директива typedef позволяет задать синоним для встроенного либо пользовательского типа данных. Например:typedef double wages;typedef vectorint vec_int;typedef vec_int test_scores;typedef bool in_attendance;typedef int *Pint;Имена, определенные с помощью директивы typedef, можно использовать точно так же, как

7.7. Директива связывания extern «C» A

7.7. Директива связывания extern «C» A Если программист хочет использовать функцию, написанную на другом языке, в частности на С, то компилятору нужно указать, что при вызове требуются несколько иные условия. Скажем, имя функции или порядок передачи аргументов различаются в

9.1.5. Директива extern «C» и перегруженные функции A

9. 1.5. Директива extern «C» и перегруженные функции A В разделе 7.7 мы видели, что директиву связывания extern «C» можно использовать в программе на C++ для того, чтобы указать, что некоторый объект находится в части, написанной на языке C. Как эта директива влияет на объявления

Параллельные секции и директива parallel sections

Параллельные секции и директива parallel sections Директива parallel sections обеспечивает параллельное выполнение нескольких операторов, простых или составных. {$omp parallel sections} begin секция 1; секция 2; …; end; Каждый оператор в блоке begin … end, следующем за директивой является отдельной

Синхронизация и директива critical

Синхронизация и директива critical Директива critical исключает параллельное выполнение следующего за ней оператора. {$omp critical имя} оператор; Этот оператор образует критическую секцию – участок кода, который не может выполняться одновременно несколькими потоками. Только

Postgres Pro Standard : Документация: 9.5: 33.9. Директивы препроцессора : Компания Postgres Professional

RU
EN
RU EN

33.9.1. Включение файлов
33.9.2. Директивы define и undef
33.9.3. Директивы ifdef, ifndef, else, elif и endif

Препроцессор ecpg поддерживает ряд директив, которые позволяют управлять разбором и обработкой исходных файлов.

33.9.1. Включение файлов

Для включения внешнего файла в программу со встраиваемым SQL, используется конструкция:

EXEC SQL INCLUDE имя_файла;
EXEC SQL INCLUDE <имя_файла>;
EXEC SQL INCLUDE "имя_файла";

Встретив такую директиву, препроцессор встраиваемого SQL будет искать файл имя_файла.h, обрабатывать его и включать в выходной код C. В результате встраиваемые операторы SQL во включённом таким образом файле будут обработаны корректно.

Препроцессор ecpg будет искать указанный файл в нескольких каталогах в следующем порядке:

  • текущий каталог
  • /usr/local/include
  • каталог включаемых файлов Postgres Pro, определённый во время сборки (например, /usr/local/pgsql/include)
  • /usr/include

Но когда используется форма EXEC SQL INCLUDE "имя_файла", просматривается только текущий каталог.

В каждом каталоге препроцессор будет сначала искать файл с заданным именем, а если не обнаружит его, попытается найти файл с добавленным расширением .h (если только заданное имя файла уже не содержит это расширение).

Заметьте, что команда EXEC SQL INCLUDE не равнозначна включению:

#include <имя_файла.h>

так как во втором случае включаемый файл не проходит через препроцессор SQL-команд. Естественно, директиву C #include можно по-прежнему применять для включения других заголовочных файлов.

Примечание

Имя включаемого файла чувствительно к регистру, несмотря на то, что остальная команда EXEC SQL INCLUDE подчиняется обычным правилам чувствительности к регистру SQL.

33.9.2. Директивы define и undef

Во встраиваемом SQL есть конструкция, подобная директиве #define, известной в C:

EXEC SQL DEFINE имя;
EXEC SQL DEFINE имя значение;

Используя её, можно определить имя:

EXEC SQL DEFINE HAVE_FEATURE;

И также можно определить константы:

EXEC SQL DEFINE MYNUMBER 12;
EXEC SQL DEFINE MYSTRING 'abc';

Удалить предыдущее определение позволяет команда undef:

EXEC SQL UNDEF MYNUMBER;

Разумеется, в программе со встраиваемым SQL можно продолжать использовать версии #define и #undef языка C. Отличие состоит в том, когда вычисляются определяемые значения. Когда применяется команда EXEC SQL DEFINE, вычислять определения и подставлять значения будет препроцессор ecpg. Например, если написать:

EXEC SQL DEFINE MYNUMBER 12;
...
EXEC SQL UPDATE Tbl SET col = MYNUMBER;

подстановку выполнит ecpg и компилятор C никогда не увидит имени или идентификатора MYNUMBER. Заметьте, что с другой стороны #define не подходит для определения константы, которую вы хотите использовать во встраиваемом SQL, так как препроцессор встраиваемого SQL не сможет увидеть это определение.

33.9.3. Директивы ifdef, ifndef, else, elif и endif

Для условной компиляции блоков кода можно использовать следующие указания:

EXEC SQL ifdef имя;

Проверяет имя и обрабатывает последующие строки, если имя было определено командой EXEC SQL define имя.

EXEC SQL ifndef имя;

Проверяет имя и обрабатывает последующие строки, если имя не было определено командой EXEC SQL define имя.

EXEC SQL else;

Начинает альтернативную ветвь условия, открытого командой EXEC SQL ifdef имя или EXEC SQL ifndef имя.

EXEC SQL elif имя;

Проверяет имя и начинает альтернативную ветвь условия, если имя было определено командой EXEC SQL define имя.

EXEC SQL endif;

Завершает ветвь условия.

Пример:

EXEC SQL ifndef TZVAR;
EXEC SQL SET TIMEZONE TO 'GMT';
EXEC SQL elif TZNAME;
EXEC SQL SET TIMEZONE TO TZNAME;
EXEC SQL else;
EXEC SQL SET TIMEZONE TO TZVAR;
EXEC SQL endif;

#ifdef — #ifndef — #elseif — #elif — #else

#ifdef — #ifndef — #elseif — #elif — #else — #endif
Далее: #эхо — #ошибка Up: директивы препроцессора Предыдущий: #undef

#ifdef , #ifndef , #elseif , #элиф , #еще и #endif — логические директивы препроцессора. Эти логические операции определяют судьба информации обрабатывается препроцессором. Синтаксис условных директив следующий: #ifdef Имя0 строк для оценки, определено ли Name0 #elseif Имя1 строк для оценки, если Name1 определено, а Name0 равно Не определено #elif ИмяN строк для оценки, определено ли NameN, а Name0-Name(N-1) равно Не определено #еще строк для оценки, если Name0-NameN Не определено #endif

и

#ifndef Имя0 строк для оценки, если Name0 равно Не определено #elseif Имя1 строк для оценки, если Name1 определено, а Name0 равно определено #еще строк для оценки, если Name0 определено и Name1 равно Не определено #конец

Выражение #ifdef Имя оценивается как истинное в Имя имеет было #define d. В этом случае (правда) строки входного файла обрабатываются до #elseif , #else или #endif встречается директива. #elseif , #else и #endif директивы действительны только после директивы #ifdef . Если Директива #ifdef оценена как истинная, то эти директивы ( #elseif , #else и #endif ) остановить обработку входных строк до тех пор, пока встречается директива #endif . Таким образом, код

 /* simple_ifdef.inp */
#определить ТЕСТ1
#определить ТЕСТ2
#ifdef ТЕСТ1
test1 определен, test2 и test3 не отмечены
#elseif ТЕСТ2
test1 не определен, test2 определен, test3 не отмечен
#elseif ТЕСТ3
test1 и test2 не определены, test3 определен
#еще
test1, test2, test3 не определены.
#endif
/* проверяем только TEST2 */
#ifdef ТЕСТ2
test2 определен
#endif 
оценивает как
 test1 определен, test2 и test3 не отмечены
test2 определен 

Если #ifdef оценивается как ложное, то #elseif директива обрабатывается, как если бы это была директива #ifdef . Если все директивы #elseif оцениваются как ложные, Директива #else обрабатывается, если она существует. Ввод оценивается до тех пор, пока не встретится директива #endif . А Директива #endif завершает обработку #ifdef .

#ifdef директивы могут быть вложенными, однако все директивы в данный логический уровень должен существовать в одном файле.

В следующем примере кода показано использование цепочки директив #ifdef с вложенными #ifdef с.

 /* ifdef_example.inp */
#define TEST1 100 // определить переменную.
#определить ТЕСТ2
/* обработка ввода на основе того, что было определено выше */
#ifdef ТЕСТ1
ТЕСТ1 (test1) определен
#ifdef TEST2 // еще одна проверка (вложенная в первую)
Значение TEST2 (тест2) определено
#else // еще для #ifdef TEST2
TEST1 (test1) определен, а TEST2 не определен
#endif // #endif для #ifdef TEST2
#elseif ТЕСТ2
TEST1 НЕ определен, а TEST2 (test2) определен
#еще
TEST1 и TEST2 не определены
#endif 
Он оценивается как равный
 100 (тест1) определено
Значение TEST2_DEFINED_WITHOUT_A_VALUE (test2) определено 

Выражение #ifndef Имя оценивается как истинное в Имя имеет не было #define d. Обработка продолжается аналогично директиве ifdef .

Директива #elseif функционально эквивалентна директиве #elseif . Эти директивы взаимозаменяемы.



Далее: #эхо — #ошибка Up: директивы препроцессора Предыдущий: #undef
Джефф Сиберс X88554
Пн 21 апр 09:12:07 PDT 1997

[Глава 2] 2.4 Без препроцессора

Глава 2
Чем Java отличается от C


Java не включает никаких препроцессоров, таких как C. 9Препроцессор 0183 cpp . Это может показаться трудным представить программирование без #define, #include и #ifdef, но на самом деле Java действительно не требует эти конструкции.

Определение констант

Любая переменная, объявленная final в Java, является константа — ее значение должно быть указано с помощью инициализатора когда оно объявлено, и это значение никогда не может быть изменено. Java-эквивалентом C #define’ed константы является статическая конечная переменная, объявленная в классе определение. Если компилятор может вычислить значение такого статическая конечная переменная во время компиляции, это использует вычисленное значение для предварительного вычисления другого времени компиляции константы, которые ссылаются на значение. Переменная java.lang.Math.PI — пример такой константы. Объявлено так:

общедоступный окончательный класс Math {
    ...
    public static final double PI = 3.14159.....;
    ...
}
 

Обратите внимание на две особенности этого примера. Во-первых, соглашение C использование ЗАГЛАВНЫХ букв для констант также является Java соглашение. Во-вторых, обратите внимание на преимущество констант Java. над константами препроцессора C: константы Java глобально уникальные иерархические имена, а константы, определенные с помощью C препроцессор всегда рискует столкнуться с конфликтом имен. Также, Константы Java строго типизированы и позволяют лучше проверка типов компилятором, чем константы препроцессора C.

Определение макросов

Препроцессор C позволяет вам определять макросы — конструкцию это выглядит как вызов функции, но на самом деле это заменяется непосредственно кодом C, экономя накладные расходы вызов функции. Java не имеет эквивалента такого рода макрос, но технология компилятора продвинулась до такой степени, что макросы теперь редко нужны. Хороший компилятор Java должен автоматически иметь возможность «встраивать» короткие методы Java где это уместно.

Включая файлы

В Java нет директивы #include, но она есть. не нужен. Java определяет отображение полностью определенных имена классов (например, java.lang.Math) в каталог и файловая структура (например, java/lang/Math.class ). Этот означает, что когда компилятору Java необходимо прочитать указанный файл класса, он точно знает, где его найти и не нуждается в специальной директиве, чтобы указать, где искать.

Кроме того, Java не делает различия между объявление переменная или процедура и определение это то, что C делает. Это означает, что нет необходимости в Файлы заголовков в стиле C или прототипы функций объектный файл служит определением интерфейса и реализация для класса.

В Java есть оператор импорта, который внешне похож на препроцессор C #include директива. Однако то, что делает это утверждение, сообщить компилятору, что текущий файл использует указанные классы или классы из указанного пакета, и позволяет нам называть эти классы сокращенными имена. Например, поскольку компилятор неявно импортирует все классы java.lang пакет, мы можем обратиться к константе java.lang.Math.PI по более короткому имени Math.PI.

Условная компиляция

Java не имеет формы C #ifdef или #if директивы для выполнения условной компиляции. Теоретически условная компиляция не нужна в Java. поскольку это платформо-независимый язык, и, следовательно, существует не являются зависимостями от платформы, для которых требуется техника. В Однако на практике условная компиляция по-прежнему часто полезно в Java — для предоставления немного другого пользователя интерфейсы на разных платформах, например, или для поддержка необязательного включения отладочного кода в программы.

Хотя Java не определяет явных конструкций для условная компиляция, хороший компилятор Java (например, Sun javac ) выполняет условную компиляцию неявно, то есть он не компилирует код, если может доказать, что код никогда не будет выполнен. Как правило, это означает этот код в операторе if проверяет выражение, которое всегда ложно, не включается. Таким образом, размещение кода внутри if (false) блок эквивалентен окружению его #if 0 и #endif в C.

Условная компиляция также работает с константами, которые, как мы видели выше, являются статическими конечными переменными. А класс может определить константу следующим образом:

private static final boolean DEBUG = false;
 

С такой константой любой код внутри if (DEBUG) блок на самом деле не компилируется в файл класса.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *