Си++/Препроцессорные директивы: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
→‎Директива #include: Завершение предыдущей правки.
Метки: с мобильного устройства из мобильной версии
м орфография, стилевые правки, пунктуация, оформление
Строка 3: Строка 3:


Таких команд немного, они все начинаются со знака решётки (<code>#</code>) и должны быть в начале строки исходного кода:
Таких команд немного, они все начинаются со знака решётки (<code>#</code>) и должны быть в начале строки исходного кода:
;<code>[[#Директива define|#define]]</code>:эта директива предусматривает определение [[w:макрос|макросов]] или препроцессорных идентификаторов, простейшее применение это замены в тексте программы
;<code>[[#Директива define|#define]]</code>: эта директива предусматривает определение [[w:макрос|макросов]] или препроцессорных идентификаторов, простейшее применение это замены в тексте программы.
;<code>[[#Директива include|#include]]</code>:позволяет включать текст других файлов в текст вашей программы.
;<code>[[#Директива include|#include]]</code>: позволяет включать текст других файлов в текст вашей программы.
;<code>[[#Директива undef|#undef]]</code>:отменяет действие директивы [[#Директива define|#define]]
;<code>[[#Директива undef|#undef]]</code>: отменяет действие директивы [[#Директива define|#define]]
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#if]]</code>:организация условной обработки директив
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#if]]</code>: организация условной обработки директив.
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#ifdef]]</code>:организация условной обработки директив
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#ifdef]]</code>: организация условной обработки директивю
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#else]]</code>:организация условной обработки директив
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#else]]</code>: организация условной обработки директив.
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#endif]]</code>:организация условной обработки директив
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#endif]]</code>: организация условной обработки директив.
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#elif]]</code>:организация условной обработки директив
;<code>[[#Условные директивы #if, #ifdef, #else, #endif, #elif|#elif]]</code>: организация условной обработки директив.
;<code>[[#Директива line|#line]]</code>:управление нумерацией строк в тексте программы
;<code>[[#Директива line|#line]]</code>: управление нумерацией строк в тексте программы.
;<code>[[#Директива error|#error]]</code>:задает текст диагностического сообщения, выводящиеся при наличии ошибок
;<code>[[#Директива error|#error]]</code>: задаёт текст диагностического сообщения, выводящиеся при наличии ошибок.
;<code>[[#Директива pragma|#pragma]]</code>:зависит от среды разработки
;<code>[[#Директива pragma|#pragma]]</code>: зависит от среды разработки.
;<code>#</code>:нулевая, или пустая, директива, бездейственно пропускается
;<code>#</code>: нулевая, или пустая, директива, бездейственно пропускается.


__NOTOC__
__NOTOC__
===Директива #define===
===Директива #define===
Директива <code>#define</code> служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами. Идентификаторы, заменяющие текстовые или числовые константы, называют именованными константами. Идентификаторы, заменяющие фрагменты программ, называют макроопределениями, причем макроопределения могут иметь аргументы.
Директива <code>#define</code> служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами. Идентификаторы, заменяющие текстовые или числовые константы, называют именованными константами. Идентификаторы, заменяющие фрагменты программ, называют макроопределениями, причём макроопределения могут иметь аргументы.


Основная форма синтаксиса директивы <code>#define</code>:
Основная форма синтаксиса директивы <code>#define</code>:
Строка 24: Строка 24:
#define идентификатор текст''
#define идентификатор текст''


Так например, в программе:
Так например, в программе


#define N 5
#define N 5
Строка 47: Строка 47:
Директива #include информирует препроцессор о том, что содержание файла с заданным именем следует обрабатывать так, как будто оно присутствует в исходной программе в месте расположения этой директивы. Новый текст также может содержать директивы препроцессора. Препроцессор выполняет директивы в новом тексте, а затем продолжает обработку текста исходного файла.
Директива #include информирует препроцессор о том, что содержание файла с заданным именем следует обрабатывать так, как будто оно присутствует в исходной программе в месте расположения этой директивы. Новый текст также может содержать директивы препроцессора. Препроцессор выполняет директивы в новом тексте, а затем продолжает обработку текста исходного файла.


"Спецификация пути" это имя файла, которому может предшествовать директория. Это должно быть имя существующего файла. Синтаксис спецификации файла зависит от операционной системы, в которой компилируется программа.
''Спецификация пути'' это имя файла, которому может предшествовать имя каталога. Это должно быть имя существующего файла. Синтаксис спецификации файла зависит от операционной системы, в которой компилируется программа.


При поиске файлов препроцессор использует концепцию "стандартной" директории. Расположение стандартных директорий для файлов зависит от реализации и операционной системы. Определение стандартной директории можно найти в Вашем Руководстве по компилятору.
При поиске файлов препроцессор использует концепцию «стандартного» каталога. Расположение стандартных каталогов для файлов зависит от реализации и операционной системы. Определение стандартного каталога можно найти в руководстве по компилятору.


Препроцессор останавливает поиск сразу же после обнаружения файла с заданным именем. Если задать полную спецификацию файла, заключенную в двойные цитатные скобки (" "), то препроцессор использует ее для поиска и игнорирует стандартную директорию.
Препроцессор останавливает поиск сразу же после обнаружения файла с заданным именем. Если задать полную спецификацию файла, заключенную в двойные кавычки (<code>" "</code>), то препроцессор использует её для поиска и игнорирует стандартный каталог.


Если заключенная в двойные цитатные скобки спецификация файла является неполной, то препроцессор сначала ищет директорию "родительского" файла. Родительский файл это файл, содержащий директиву #include. Например, если файл f2 вставляется в файл f1, то f1 будет родительским файлом.
Если заключенная в двойные кавычки спецификация файла является неполной, то препроцессор сначала ищет каталог «родительского» файла. Родительский файл это файл, содержащий директиву #include. Например, если файл f2 вставляется в файл f1, то f1 будет родительским файлом.


Вставка файлов может быть вложенной. Т.е. директива #include может появляться в файле, который сам вставляется директивой #include. Файл f2 может вызывать файл f3. В этом случае f1 все еще будет родительским для f2, но "дедушкой" для f3.
Вставка файлов может быть вложенной. Т. е. директива #include может появляться в файле, который сам вставляется директивой #include. Файл f2 может вызывать файл f3. В этом случае f1 все еще будет родительским для f2, но «дедушкой» для f3.


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


Если спецификация файла заключена в угловые скобки, то препроцессор не проводит поиска в текущем рабочем каталоге. Поиск файла начинается в директориях, заданный в командной строке компилятора, а затем в стандартной директории.
Если спецификация файла заключена в угловые скобки (<code><nowiki>< ></nowiki></code>), то препроцессор не проводит поиска в текущем рабочем каталоге. Поиск файла начинается в каталогах, заданных в командной строке компилятора, а затем в стандартном каталоге.


Допускается вложение вставки файлов до 10 уровней. При обработке вложенных #include препроцессор всегда будет осуществлять вставку в первоначальный исходный файл.
Допускается вложение вставки файлов до 10 уровней. При обработке вложенных #include препроцессор всегда будет осуществлять вставку в первоначальный исходный файл.


===Директива #undef===
===Директива #undef===
Директива #undef удаляет текущее определение идентификатора. Поэтому все встречающиеся появления идентификатора будут игнорироваться предпроцессором. Для удаления определения макро с использованием #undef, нужно задать только идентификатор макро, не задавая список параметров.
Директива #undef удаляет текущее определение идентификатора. Поэтому все встречающиеся появления идентификатора будут игнорироваться предпроцессором. Для удаления определения макро с использованием #undef, нужно задать только идентификатор макро, не задавая список параметров.


Можно применить директиву #undef к идентификатору, у которого нет определения. Тем самым пользователь получает дополнительную гарантию того, что данный идентификатор не определен.
Можно применить директиву #undef к идентификатору, у которого нет определения. Тем самым пользователь получает дополнительную гарантию того, что данный идентификатор не определён.


Директива #undef обычно используется в паре с директивой #define для задания области исходной программы, в которой идентификатор имеет специальное значение. Например, некоторая функция исходной программы может иметь объявленные константы, которые задают значения среды работы, которые не влияют на остальную часть программы. Директива #undef также работает с директивой #if для управления условной компиляцией исходной программы.
Директива #undef обычно используется в паре с директивой #define для задания области исходной программы, в которой идентификатор имеет специальное значение. Например, некоторая функция исходной программы может иметь объявленные константы, которые задают значения среды работы, которые не влияют на остальную часть программы. Директива #undef также работает с директивой #if для управления условной компиляцией исходной программы.
Строка 72: Строка 72:
===Условные директивы #if, #ifdef, #else, #endif, #elif===
===Условные директивы #if, #ifdef, #else, #endif, #elif===
Эти директивы позволяют подавить компиляцию части исходного файла, проверяя постоянное выражение или идентификатор. Результат проверки определяет, какие блоки текста будут переданы в компилятор и какие блоки текста будут удалены из исходного файла при предпроцессорной обработке.
Эти директивы позволяют подавить компиляцию части исходного файла, проверяя постоянное выражение или идентификатор. Результат проверки определяет, какие блоки текста будут переданы в компилятор и какие блоки текста будут удалены из исходного файла при предпроцессорной обработке.

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


===Директива #line===
===Директива #line===
Изменяет внутренний номер строки и имя файла компилятора. Если имя файла опущено, оно остается прежним. Cинтаксис директивы:
Изменяет внутренний номер строки и имя файла компилятора. Если имя файла опущено, оно остается прежним. Cинтаксис директивы:
#line константа <"имя_файла">
#line константа <"имя_файла">
к примеру #line 1000 "file.сpp" устанавливается имя исходного файла file.сpp и текущий номер строки 1000.
к примеру <code>#line 1000 "file.сpp"</code> устанавливается имя исходного файла file.сpp и текущий номер строки 1000.
Текущий номер строки и имя файла доступны через константы препроцессора __LINE__ и __FILE__.
Текущий номер строки и имя файла доступны через константы препроцессора __LINE__ и __FILE__.


===Директива #error===
===Директива #error===
Директива #error создает заданное пользователем сообщение об ошибке во время компиляции, а затем завершает компиляцию.
Директива #error создаёт заданное пользователем сообщение об ошибке во время компиляции, а затем завершает компиляцию.

- Синтаксис:
#errortoken-string


Синтаксис:
- Заметки:
#errortoken-string


Сообщение об ошибке, создаваемое этой директивой, содержит параметр token-string.Параметр token-string не подлежит расширению макроса.Эта директива наиболее полезна в ходе предварительной обработки и позволяет уведомлять разработчика о противоречиях в программе или о нарушении ограничений.В следующем примере демонстрируется обработка ошибки во время предварительной обработки.
Примечание: Сообщение об ошибке, создаваемое этой директивой, содержит параметр token-string. Параметр token-string не подлежит расширению макроса. Эта директива наиболее полезна в ходе предварительной обработки и позволяет уведомлять разработчика о противоречиях в программе или о нарушении ограничений. В следующем примере демонстрируется обработка ошибки во время предварительной обработки.


- Пример использования:
Пример использования:
#if !defined(__cplusplus)
#if !defined(__cplusplus)
#error C++ compiler required.
#error C++ compiler required.
#endif
#endif


===Директива #pragma===
===Директива #pragma===
<nowiki>#</nowiki>pragma это инструкция компилятору, которая определяется реализацией.
<nowiki>#</nowiki>pragma это инструкция компилятору, которая определяется реализацией.
Конструкция #pragma в языке Си/Си++ используется для задания дополнительных указаний компилятору. С помощью этих конструкций можно указать как осуществлять выравнивание данных в структурах, запретить выдавать определенные предупреждения и так далее.
Конструкция #pragma в языке Си/Си++ используется для задания дополнительных указаний компилятору. С помощью этих конструкций можно указать как осуществлять выравнивание данных в структурах, запретить выдавать определённые предупреждения и так далее.


===Замены в тексте===
===Замены в тексте===

Версия от 05:08, 3 марта 2019

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

Таких команд немного, они все начинаются со знака решётки (#) и должны быть в начале строки исходного кода:

#define
эта директива предусматривает определение макросов или препроцессорных идентификаторов, простейшее применение это замены в тексте программы.
#include
позволяет включать текст других файлов в текст вашей программы.
#undef
отменяет действие директивы #define
#if
организация условной обработки директив.
#ifdef
организация условной обработки директивю
#else
организация условной обработки директив.
#endif
организация условной обработки директив.
#elif
организация условной обработки директив.
#line
управление нумерацией строк в тексте программы.
#error
задаёт текст диагностического сообщения, выводящиеся при наличии ошибок.
#pragma
зависит от среды разработки.
#
нулевая, или пустая, директива, бездейственно пропускается.


Директива #define

Директива #define служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами. Идентификаторы, заменяющие текстовые или числовые константы, называют именованными константами. Идентификаторы, заменяющие фрагменты программ, называют макроопределениями, причём макроопределения могут иметь аргументы.

Основная форма синтаксиса директивы #define:

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

Так например, в программе

#define N 5
int main()
{
    int a;
    a = N;
    return 0;
}

Переменная а примет значение 5.

Директива #include

#include "спецификация-пути"

#include <спецификация-пути>


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

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

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

При поиске файлов препроцессор использует концепцию «стандартного» каталога. Расположение стандартных каталогов для файлов зависит от реализации и операционной системы. Определение стандартного каталога можно найти в руководстве по компилятору.

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

Если заключенная в двойные кавычки спецификация файла является неполной, то препроцессор сначала ищет каталог «родительского» файла. Родительский файл это файл, содержащий директиву #include. Например, если файл f2 вставляется в файл f1, то f1 будет родительским файлом.

Вставка файлов может быть вложенной. Т. е. директива #include может появляться в файле, который сам вставляется директивой #include. Файл f2 может вызывать файл f3. В этом случае f1 все еще будет родительским для f2, но «дедушкой» для f3.

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

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

Допускается вложение вставки файлов до 10 уровней. При обработке вложенных #include препроцессор всегда будет осуществлять вставку в первоначальный исходный файл.

Директива #undef

Директива #undef удаляет текущее определение идентификатора. Поэтому все встречающиеся появления идентификатора будут игнорироваться предпроцессором. Для удаления определения макро с использованием #undef, нужно задать только идентификатор макро, не задавая список параметров.

Можно применить директиву #undef к идентификатору, у которого нет определения. Тем самым пользователь получает дополнительную гарантию того, что данный идентификатор не определён.

Директива #undef обычно используется в паре с директивой #define для задания области исходной программы, в которой идентификатор имеет специальное значение. Например, некоторая функция исходной программы может иметь объявленные константы, которые задают значения среды работы, которые не влияют на остальную часть программы. Директива #undef также работает с директивой #if для управления условной компиляцией исходной программы.

Условные директивы #if, #ifdef, #else, #endif, #elif

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

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

Директива #line

Изменяет внутренний номер строки и имя файла компилятора. Если имя файла опущено, оно остается прежним. Cинтаксис директивы:

#line константа <"имя_файла">

к примеру #line 1000 "file.сpp" устанавливается имя исходного файла file.сpp и текущий номер строки 1000. Текущий номер строки и имя файла доступны через константы препроцессора __LINE__ и __FILE__.

Директива #error

Директива #error создаёт заданное пользователем сообщение об ошибке во время компиляции, а затем завершает компиляцию.

Синтаксис:

#errortoken-string

Примечание: Сообщение об ошибке, создаваемое этой директивой, содержит параметр token-string. Параметр token-string не подлежит расширению макроса. Эта директива наиболее полезна в ходе предварительной обработки и позволяет уведомлять разработчика о противоречиях в программе или о нарушении ограничений. В следующем примере демонстрируется обработка ошибки во время предварительной обработки.

Пример использования:

#if !defined(__cplusplus)
#error C++ compiler required.
#endif

Директива #pragma

#pragma это инструкция компилятору, которая определяется реализацией. Конструкция #pragma в языке Си/Си++ используется для задания дополнительных указаний компилятору. С помощью этих конструкций можно указать как осуществлять выравнивание данных в структурах, запретить выдавать определённые предупреждения и так далее.

Замены в тексте

Помогите написанию данной статьи

Макросы

Предопределенные макроимена