Что такое ifndef c

Урок №22. Директивы препроцессора

Обновл. 11 Сен 2021 |

Препроцессор лучше всего рассматривать как отдельную программу, которая выполняется перед компиляцией. При запуске программы, препроцессор просматривает код сверху вниз, файл за файлом, в поиске директив. Директивы — это специальные команды, которые начинаются с символа # и НЕ заканчиваются точкой с запятой. Есть несколько типов директив, которые мы рассмотрим ниже.

Директива #include

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

Директива #include имеет две формы:

Директива #define

Директиву #define можно использовать для создания макросов. Макрос — это правило, которое определяет конвертацию идентификатора в указанные данные.

Есть два основных типа макросов: макросы-функции и макросы-объекты.

Макросы-функции ведут себя как функции и используются в тех же целях. Мы не будем сейчас их обсуждать, так как их использование, как правило, считается опасным, и почти всё, что они могут сделать, можно осуществить с помощью простой (линейной) функции.

Макросы-объекты можно определить одним из следующих двух способов:

#define идентификатор текст_замена

Макросы-объекты с текст_замена

Источник

##директивы ifdef и ifndef

Директивы препроцессора, которые определяют, определена ли конкретная константа препроцессора или макрос.

#идентификатор ifdef.
#endif
#идентификатор ifndef.
#endif

Параметры

ЭлементОписание
ИдентификаторИдентификатор проверяемой константы или макроса.

Remarks

Эти директивы предназначены только для совместимости с предыдущими версиями языка. Рекомендуется использовать определенный оператор с # директивой if.

#Директива ifndef проверяет наличие противоположного условия, установленного параметром # ifdef. Если идентификатор не определен, условие имеет значение true (не равно нулю); в противном случае условие имеет значение false (ноль).

Примеры

Значение идентификатора можно передать из командной строки при помощи параметра /D. Он позволяет определить до 30 макросов. Это позволяет проверить, существует ли определение, поскольку определения можно передавать из командной строки. В следующем примере это поведение используется для определения того, следует ли запускать приложение в тестовом режиме.

При компиляции с помощью следующей команды Prog. cpp будет компилироваться в тестовом режиме. в противном случае он будет компилироваться в окончательном режиме.

Источник

Русские Блоги

Магия условной компиляции #ifdef

Эта статья в основном знакомит с предварительно скомпилированными инструкциями, относящимися к условной компиляции на языке Си, включая определенные #define, #undef, #ifdef, #ifndef, #if, #elif, #else, #endif.
#define Определить макрос предварительной обработки
#undef Неопределить макрос

#if Компилировать условные команды в предварительной обработке, эквивалентно операторам if в синтаксисе C
#ifdef Определите, определен ли макрос. Если он определен, выполните следующую инструкцию
#ifndef В отличие от #ifdef, определите, является ли макрос неопределенным
#elif Если условия #if, #ifdef, #ifndef или предыдущие #elif не выполнены, выполняются операторы после #elif, что эквивалентно else-if в синтаксисе C
#else соответствует #if, #ifdef, #ifndef, если эти условия не выполняются, выполняются операторы после #else, что эквивалентно остальному в синтаксисе C
#endif #if, #ifdef, #ifndef Флаги окончания этих условных команд.
определено Используйте с #if, #elif, чтобы определить, определен ли макрос
Во-вторых, условная компиляция

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

1 #ifndef ABCD_H
2 #define ABCD_H
3
4 // … some declaration codes
5
6 #endif // #ifndef ABCD_H

В файле реализации обычно есть похожие определения:
Скопировать код

1 #ifdef _DEBUG
2
3 // … do some operations
4
5 #endif
6
7 #ifdef _WIN32
8
9 // … use Win32 API
10
11 #endif

Это общие ситуации для условной компиляции.
В-третьих, предварительно скомпилированные инструкции, используемые при условной компиляции

#define Определение макроса предварительной обработки
#undef Неопределить макрос

#if Компилировать условные команды в предварительной обработке, эквивалентно операторам if в синтаксисе C
#ifdef Определите, определен ли макрос. Если он определен, выполните следующую инструкцию
#ifndef В отличие от #ifdef, определите, является ли макрос неопределенным
#elif Если условия #if, #ifdef, #ifndef или предыдущие #elif не выполнены, выполняются операторы после #elif, что эквивалентно else-if в синтаксисе C
#else соответствует #if, #ifdef, #ifndef, если эти условия не выполняются, выполняются операторы после #else, что эквивалентно остальному в синтаксисе C
#endif #if, #ifdef, #ifndef Флаги окончания этих условных команд.
определено Используйте с #if, #elif, чтобы определить, определен ли макрос
В-четвертых, примеры применения предварительно скомпилированных инструкций

Определения макросов обычно делятся на объектные макросы и функциональные макросы с параметрами или без параметров.
Макрос объекта: Макросы без параметров называются «объектоподобными макросами». Макросы объектов в основном используются для определения констант и общих идентификаторов. Например:

// постоянное определение
#define MAX_LENGTH 100
// Общий логотип, макрос вывода журнала
#define SLog printf
// предварительно скомпилированный макрос
#define _DEBUG

Макрос функции: Макрос с параметрами. Использование макросов может повысить эффективность выполнения кода: вызовы подпрограмм должны быть вытолкнуты из стека, и этот процесс будет потреблять много вычислительных ресурсов ЦП, если он будет слишком частым. Следовательно, некоторый код с небольшим количеством кода, но часто выполняемый, улучшит эффективность выполнения кода, если он будет реализован с помощью макрокоманд параметров. Тем не менее, большинство программ на C ++ не рекомендуют использовать макросы функций, которые трудно отладить. Попробуйте вместо этого использовать встроенный C ++. Например:

// минимальная функция
#define MIN(a,b) ((a)>(b)? (a):(b))
// безопасно отключаем функцию памяти
#define SAFE_DELETE§ >

#undef может отменить определение макроса, соответствующее #define.
2. defined

определенный используется, чтобы проверить, определен ли макрос. define (name): Возвращает 1, если макрос определен, в противном случае возвращает 0.
Он используется в сочетании с #if, #elif, #else для определения, определен ли макрос. На первый взгляд он кажется избыточным, поскольку уже есть #ifdef и #ifndef. определено может использоваться для объявления нескольких условий суждения в суждении суждения; #ifdef и #ifndef поддерживают только оценку, определен ли макрос

В отличие от #if, #elif, #else, #ifdef, #ifndef и определенные тестовые макросы могут быть как объектными, так и функциональными макросами.
3. #ifdef、#ifndef、#else、#endif

Относительно часто используемые предварительно скомпилированные инструкции в условной компиляции. Шаблон выглядит следующим образом:
Скопировать код

#ifdef ABC
// … codes while definded ABC
#elif (CODE_VERSION > 2)
// … codes while CODE_VERSION > 2
#else
// … remained cases
#endif // #ifdef ABC

#ifdef используется для определения того, определен ли макрос. Он противоположен #ifndef. Оба поддерживают только определение того, был ли определен один макрос. В вышеприведенном примере они взаимозаменяемы. Если предварительная компиляция с несколькими условиями не требуется, #elif и #else в приведенном выше примере могут быть опущены.
4. #if、#elif、#else、#endif

#if поддерживает оценку наличия нескольких макросов одновременно и может использоваться с константными выражениями. Общие форматы следующие:
Скопировать код

#if Постоянное выражение 1
// … some codes
#elif константное выражение 2
// … other codes
#elif константное выражение 3
// …

#else
// … statement
#endif

Константное выражение может быть допустимым константным выражением C, содержащим макросы, арифметические операции, логические операции и т. Д. Если константное выражение является неопределенным макросом, его значение рассматривается как 0.

#if MACRO_NON_DEFINED // эквивалентно

Вы должны избегать использования #if при определении, определен ли макрос, потому что значение макроса может быть определено как 0. Вместо этого используйте #ifdef или #ifndef.
Примечание. Макросы после #if и #elif могут быть только объектными макросами. Если макрос не определен или макрос является функциональным макросом, у компилятора может появиться предупреждение о том, что соответствующий макрос не определен.
5. Резюме

Эта статья в основном представляет предварительно скомпилированные инструкции на языке Си. Целью написания этой статьи является прояснение связанных концептуальных вызовов и поиск наиболее подходящих инструкций и форматов при их использовании в последующей предварительной компиляции. Например, выполняется одновременная предварительная компиляция нескольких определений макросов, предварительная компиляция с несколькими ветвями и взаимодействие команд #elif и #else.

Во-первых, если условная компиляция, выберите компиляцию
(1)
#if ()
//*******
#endif
(2)
#if ()
//******
#else
//******
#endif
(3)
#if ()
//******
#elif ()
//******
#elif ()
//******
#endif
2. Обратите внимание, что вы не можете добавить здесь «()», в противном случае скобки также будут обрабатываться как строка определения макроса.
#define DBG
3.
#define A C(0、1…)
4. Обратите внимание, что здесь нельзя добавить «()», в противном случае скобки также будут рассматриваться как строка, определенная макросом.
#define DBG
#undefine DBG
5. Обратите внимание, что здесь нельзя добавить «()», в противном случае скобки также будут обрабатываться как строка, определенная макросом.
(1)
#ifdef DBG
#define UNDBG
#define UNDBG1
#endif
(2)
#ifundef DBG
#define UNDBG
#define UNDBG
#endif

#include
#define BB
#ifdef AA
#define HELLO “hello world”
#elif BB
#define HELLO “hello CC”
#endifint main()
<
printf(«%s\n»,HELLO);
return 1;
>

Эти макросы предназначены для условной компиляции. В общем случае все строки в исходной программе компилируются. Однако иногда желательно компилировать часть контента только при соблюдении определенных условий, то есть указывать условия компиляции для части контента. Иногда желательно скомпилировать набор операторов, когда определенное условие выполнено, и скомпилировать другой набор операторов, когда условие не выполнено.
Наиболее распространенная форма команды условной компиляции :
#ifdef идентификатор
Сеть 1
#else
Сеть 2
#endif

О чудесном использовании #ifdef в разработке программного обеспечения

Автор занимается разработкой и обслуживанием определенного прикладного программного обеспечения в среде UNIX. Пользователи распределены по всей стране. Основные функции, которые требуются каждому пользователю, одинаковы. Однако некоторые функции должны постоянно обновляться по мере изменения требований. Обновление пользователей по всей стране очень сложно, и мы просто используем электронную почту для отправки исправлений пользователям. Эти исправления основаны на наборе программного обеспечения, которое постоянно модифицируется и расширяется и пишется различными Файл логотипа передается в разные модули. Хотя объем программы постоянно расширяется, он никак не влияет на функции старых пользователей, что в основном связано с ролью # ifdef / # else / # endif в программе на Си.

В основном мы используем следующие методы, предполагая, что мы определили #ifdef DEBUG и #ifdef TEST в заголовке программы:

1. Используйте # ifdef / # endif, чтобы включить программный функциональный модуль для предоставления функции пользователю.

Определите #ifdef HNLD в заголовке программы:

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

2. Добавьте отметку перед каждой подпрограммой, чтобы отслеживать выполнение программы.

3. Избегайте аппаратных ограничений. Иногда аппаратные средства некоторых конкретных прикладных сред отличаются, но из-за условий локального отсутствия такого оборудования, поэтому обходят аппаратное обеспечение и пишут ожидаемые результаты напрямую. Конкретный подход:

// Обходим этот оператор, когда выполняется отладка программы

После отладки замаскируйте определение TEST и перекомпилируйте, а затем отправьте его пользователю.

ifdef #ifndef и другое использование (очередь)

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

Лучше поместить содержимое заголовочных файлов в #ifndef и #endif. Независимо от того, ссылаются ли на ваши заголовочные файлы несколько файлов, вы должны добавить это. Общий формат таков:

#ifndef STDIO_H
#define STDIO_H

2. Проблемы с определением переменных в #ifndef (обычно не определяются в #ifndef).

#ifndef AAA
#define AAA

int i;

#endif
есть определение переменной
При линковке в vc я обнаружил ошибку повторного определения i и успешно скомпилировал в c.

(3). Результаты соединения языка C и языка C ++ различны, возможно (догадывается), что при компиляции язык C ++ будет глобальным
Переменная по умолчанию имеет сильный символ, поэтому произошла ошибка соединения. Язык C определяет, будет ли он инициализирован в зависимости от того, инициализирован он или нет. (Ссылка)

#ifndef X_H
#define X_H
extern int i;
#endif //X_H

int i;

Обратите внимание на проблему:

Источник

Ifdef c что это

Другой метод условной компиляции состоит в использовании директив #ifdef и #ifndef, что соответ­ственно означает «если определено» и «если не определено». Стандартный вид #ifdef следующий:

#ifdef имя_макроса
последовательность операторов
#endif

Если имя макроса определено ранее в операторе #define, то последовательность операторов, сто­ящих между #ifdef и #endif, будет компилироваться. Стандартный вид #ifndef следующий:

#ifndef имя_макроса
последовательность операторов
#endif

Если имя макроса не определено ранее в операторе #define, то последовательность операторов, стоящих между #ifdef и #endif, будет компилироваться.

Kaк #ifdef, так и #ifndef могут использовать оператор #else, но нe #elif. Например:

#include
#define TED 10
int main(void)

выводит «Hi Ted» и «RALPH not defined». Если TED не определен, то выведется «Hi anyone», a за ним «RALPH not defined».

#ifdef и #ifndef можно вкладывать друг в друга так же, как и #if.

Синтаксис Syntax

#ifdef идентификатор #ifdef identifier
#ifndef идентификатор #ifndef identifier

Эти директивы эквивалентны следующим: These directives are equivalent to:

Примечания Remarks

Блок, относящийся только к системам Microsoft Microsoft Specific

Директива #ifdef полезна для проверки существования определения, так как определение может быть передано из командной строки. The #ifdef directive is useful for checking whether a definition exists, because a definition can be passed from the command line. Например: For example:

Завершение блока, относящегося только к системам Майкрософт END Microsoft Specific

Содержание

Основные функции препроцессора [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

Препроцессором выполняются следующие действия:

Условная компиляция позволяет выбрать код для компиляции в зависимости от:

Этапы работы препроцессора:

Язык препроцессора C/C++ не является полным по Тьюрингу хотя бы потому, что с помощью директив невозможно заставить препроцессор зависнуть. См. рекурсивная функция (теория вычислимости).

Синтаксис директив [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

Директивой (командной строкой) препроцессора называется строка в исходном коде, имеющая следующий формат: #ключевое_слово параметры :

Список ключевых слов:

Описание директив [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

Вставка файлов (#include) [ править | править код ]

Для #include «. » поиск файла выполняется в текущей папке и папках, указанных в командной строке компилятора. Для #include поиск файла выполняется в папках, содержащих файлы стандартной библиотеки (пути к этим папкам зависят от реализации компилятора).

Включаемые файлы обычно содержат:

Директива #include обычно указывается в начале файла (в заголовке), поэтому включаемые файлы называются заголовочными.

Пример включения файлов из стандартной библиотеки языка C.

Использование препроцессора считается неэффективным по следующим причинам:

Константы и макросы #define [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

Константы и макросы препроцессора используются для определения небольших фрагментов кода.

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

Пример. Определение макроса max, принимающего два аргумента: a и b.

Макрос вызывается так же, как и любая функция.

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

Однако, наряду с преимуществами использования макросов в языке Си, например, для определения обобщённых типов данных или отладочных инструментов, они также несколько снижают эффективность их применения и даже могут привести к ошибкам.

Например, если f и g — две функции, вызов

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

Макросы Си могут походить на функции, создавая новый синтаксис в некоторых пределах, а также могут быть дополнены произвольным текстом (хотя компилятор Си требует, чтобы текст был без ошибок написанным Си-кодом или оформлен как комментарий), но у них есть некоторые ограничения как у программных конструкций. Макросы, схожие с функциями, например, могут быть вызваны как «настоящие» функции, но макрос не может быть передан другой функции при помощи указателя, по той причине, что макрос сам по себе не имеет адреса.

Некоторые современные языки обычно не используют такой способ метапрограммирования с использованием макросов как дополнений строк символов, в расчете или на автоматическое или на ручное подключение функций и методов, а вместо этого другие способы абстракции, такие как шаблоны, обобщённые функции или параметрический полиморфизм. В частности, встраиваемые функции [en] позволяют избежать одного из главных недостатков макросов в современных версиях Си и C++, так как встроенная функция обеспечивает преимущество макросов в снижении накладных расходов при вызове функции, но её адрес можно передавать в указателе для косвенных вызовов или использовать в качестве параметра. Аналогично, проблема множественных вычислений, упомянутая выше в макросе max, для встроенных функций неактуальна.

Операторы # и ## [ править | править код ]

Эти операторы используются при создании макросов. Оператор # перед параметром макроса обрамляет его в двойные кавычки, например:

препроцессор преобразует в:

Оператор ## в макросах объединяет две лексемы, например:

препроцессор преобразует в:

Формальное описание макроподстановок [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

1) Управляющая строка следующего вида заставляет препроцессор заменять идентификатор на последовательность лексем везде далее по тексту программы:

При этом символы пустого пространства в начале и в конце последовательности лексем выбрасываются. Повторная строка #define с тем же идентификатором считается ошибкой, если последовательности лексем не идентичны (несовпадения в символах пустого пространства не играют роли).

2) Строка следующего вида, где между первым идентификатором и открывающей круглой скобкой не должно быть символов пустого пространства, представляет собой макроопределение с параметрами, задаваемыми списком-идентификаторов.

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

Управляющая строка следующего вида приказывает препроцессору «забыть» определение, данное идентификатору:

Применение директивы #undef к не определенному ранее идентификатору не считается ошибкой.

На процесс подстановки влияют два специальных знака операций.

Восклицательным знаком (!) отмечены правила, отвечающие за рекурсивные вызов и определения.

Пример раскрытия макроопределения [ править | править код ]

Вызов макроса «cat(var, 123)» будет заменён на «var123». Однако вызов «cat(cat(1, 2), 3)» не даст желаемого результата. Рассмотрим шаги работы препроцессора:

Операция «##» помешала правильному раскрытию аргументов второго вызова «cat». В результате получилась следующая цепочка лексем:

где «)3» — результат сцепления последней лексемы первого аргумента с первой лексемой второго аргумента, не является допустимой лексемой.

Можно задать второй уровень макроопределения в таком виде:

Вызов «xcat(xcat(1, 2), 3)» будет заменён на «123». Рассмотрим шаги работы препроцессора:

Всё прошло благополучно, потому что в раскрытии макроса «xcat» не участвовал оператор «##».

Предопределённые константы #define [ править | править код ]

Константы, создаваемые препроцессором автоматически:

Условная компиляция [ править | править код ]

Препроцессор языка Си предоставляет возможность компиляции с условиями. Это допускает возможность существования различных версий одного кода. Обычно такой подход используется для настройки программы под платформу компилятора, состояние (отлаживаемый код может быть выделен в результирующем коде) или возможность проверки подключения файла строго один раз.

В общем случае, программисту необходимо использовать конструкцию типа:

Такая «защита макросов» предотвращает двойное подключение заголовочного файла путём проверки существования этого макроса, который имеет то же самое имя, что и заголовочный файл. Определение макроса FOO_H происходит, когда заголовочный файл впервые обрабатывается препроцессором. Затем, если этот заголовочный файл вновь подключается, FOO_H уже определен, в результате чего препроцессор пропускает полностью текст этого заголовочного файла.

То же самое можно сделать, включив в заголовочный файл директиву:

Условия препроцессора можно задавать несколькими способами, например:

Этот способ часто используется в системных заголовочных файлах для проверки различных возможностей, определение которых может меняться в зависимости от платформы; например, библиотека Glibc использует макросы с проверкой особенностей с целью проверить, что операционная система и оборудование их (макросы) корректно поддерживает при неизменности программного интерфейса.

Диграфы и триграфы [ править | править код ]

Что такое ifndef c. Смотреть фото Что такое ifndef c. Смотреть картинку Что такое ifndef c. Картинка про Что такое ifndef c. Фото Что такое ifndef c

Препроцессор считает последовательность «%:%:» двумя токенами при обработке кода C и одним токеном при обработке кода C++.

Источник

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

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