Невозможно отобразить презентацию
Similar presentations:
Препроцессорные средства
Тема № 10.
Препроцессорные средства 10.1.
Стадии и основные команды препроцессорной обработки Препроцессор языка Си (Си++) представляет собой программу (подпрограмму), которая используется для обработки исходного файла на нулевой фазе компиляции.
Чаще всего препроцессор не отдельная программа, а входит в состав компилятора.
Директивы препроцессора представляют инструкции, записанные в исходном тексте программы.
Они обычно используются для того, чтобы облегчить модификацию исходных программ и сделать их более независимыми от особенностей различных реализаций компилятора языка Си, разных компьютеров и операционных сред.
Стадии препроцессорной обработки 1.Все системно-зависимые обозначения (например, системно-зависимый индикатор конца строки) перекодируются в стандартные коды.
2.Каждая пара символов «\» и «конец строки» убираются, и тем самым следующая строка присоединяется к исходной.
3.В тексте распознаются директивы препроцессора, а каждый комментарий заменяется пробелом.
4.Выполняются директивы препроцессора и выполняются макроподстановки.
5.ESC-последовательности в строках (символах) заменяются на их эквиваленты (числовые коды).
6.Смежные символьные строки объединяются в одну строку.
С помощью директив препроцессора можно выполнять следующие действия
• заменять идентификаторы заранее подготовленными последовательностями символов;
• включать тексты из файлов;
• исключать из текста программы отдельные его части (условная компиляция);
• заменять обозначения параметризованным текстом (макроподстановки).
Определены следующие препроцессорные директивы: #define #include #undef #if #ifdef #else #endif #elif #line #error # ## Указание компилятору: #pragma 10.2.
Замены в тексте Формат: #define <идентификатор> [<текст>] Директива может располагаться в любом месте обрабатываемого текста, ее действие от точки размещения до конца текста.
Директива определяет идентификатор как препроцессорный (это условие можно далее использовать для условной компиляции).
В результате обработки вхождения идентификатора заменяются текстом, окончание которого признак конца строки.
Символы пробела в начале и конце текста в подстановке не участвуют.
Если текст слишком длинный его можно продолжить на другой строке, использую символ «\».
Идентификатор можно переопределять с помощью другого использования #define или отменить его действие с помощью директивы #undef <идентификатор> 10.3.
Макроподстановки Макрос – это средство замены одной последовательности символов другой (замена в тексте простейшая форма макроса).
Большими возможностями обладают макроопределения с параметрами.
Формат: #define <идентификатор>(<список_параметров>) <текст> Примеры: #define max(a, b) a<b?b:a Вхождение в программу max(x, 10) заменяется на x<10? 10:x #define abs(x) x>=0?x:-x Вхождение в программу abs(a) заменяется на a>=0?a:-a Отличие макросов от функций 1.Функции имеют код (за исключением inline- функций) в одном экземпляре, а коды макроса вставляются в программу столько раз сколько используется макрос, причем подстановка для макроса осуществляется всегда.
2.Функции работают с определенными типами параметров, макрос пригоден для обработки параметров любого типа, допустимых в выражении строки замещения.
Механизм перегрузки и шаблоны функций в Си++ позволяют решать те же задачи.
10.4.
Включение текстов из файлов Формат: #include “путь_к_файлу” #include <путь_к_файлу> Включает текст файла в текущий компилируемый файл, когда используются “” файл в первую очередь ищется в текущем каталоге, а затем в системных, а когда <>, то файл ищется в первую очередь в системных каталогах, а затем в текущем.
10.5.
Условная компиляция 1-ая форма: #if <конст_выражение1> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif 2-ая форма #ifdef <идентификатор> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif 3 форма #ifndef <идентификатор> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif Вместо директив #ifdef и #ifndef можно использовать более старые формы: #if defined(<идентификатор>) #if !defined(<идентификатор>) defined(<идентификатор>) – может использоваться в качестве ограниченного константного выражения, например, после #elif Директивы условной компиляции могут использоваться для отладочных печатей, для защиты заголовочных файлов от повторного включения, а также для повышения переносимости программ.
10.6.
Директива нумерации строк #line <константа> [“имя_файла”] Директива сообщает компилятору об изменении имени файла и порядка нумерации строк (следующая строка имеет номер константа+1).
Влияет на диагностические сообщения компилятора.
10.7.
Директива обработки ошибок Формат: #error <текст> Происходит печать текста, как правило, используется совместно с директивами условной компиляции.
Препроцессор прерывает компиляцию и выдает сообщение.
10.8.
Директивы # и ## Для повышения читабельности программ может использоваться пустая директива, состоящая из строки с символом #.
Кроме того, символ # может помещаться перед аргументом в строке текста макроопределения и указывает на необходимость его преобразования с символьную строку (помещается в “ “).
Директива ## используется в строке замещения в макроопределениях для склейки лексем.
10.9.
Заранее определенные препроцессорные идентификаторы __TIME__ __DATE__ __FILE__ __LINE__ _WIN32 _M_IX86 // Определяет используемый процессор __cplusplus _DLL UNICODE и др.
10.10.
Указания компилятору #pragma <последовательность_символов> Определяет зависящие от реализации указания компилятору (прагмы).
Компилятор Visual C++ поддерживает следующие прагмы: alloc text, comment, optimize, auto_inline, component, inline_depth, pack, bss seg, data_seg, function, intrinsic, setlocale, code_seg, hdrstop, message, const seg, once, warning, inline recursion, check_stack, include_alias Например,директива #pragma warning(disable: 4305) предписывает компилятору не выдавать предупреждения при несовпадении типов данных #pragma inline
Препроцессорные средства 10.1.
Стадии и основные команды препроцессорной обработки Препроцессор языка Си (Си++) представляет собой программу (подпрограмму), которая используется для обработки исходного файла на нулевой фазе компиляции.
Чаще всего препроцессор не отдельная программа, а входит в состав компилятора.
Директивы препроцессора представляют инструкции, записанные в исходном тексте программы.
Они обычно используются для того, чтобы облегчить модификацию исходных программ и сделать их более независимыми от особенностей различных реализаций компилятора языка Си, разных компьютеров и операционных сред.
Стадии препроцессорной обработки 1.Все системно-зависимые обозначения (например, системно-зависимый индикатор конца строки) перекодируются в стандартные коды.
2.Каждая пара символов «\» и «конец строки» убираются, и тем самым следующая строка присоединяется к исходной.
3.В тексте распознаются директивы препроцессора, а каждый комментарий заменяется пробелом.
4.Выполняются директивы препроцессора и выполняются макроподстановки.
5.ESC-последовательности в строках (символах) заменяются на их эквиваленты (числовые коды).
6.Смежные символьные строки объединяются в одну строку.
С помощью директив препроцессора можно выполнять следующие действия
• заменять идентификаторы заранее подготовленными последовательностями символов;
• включать тексты из файлов;
• исключать из текста программы отдельные его части (условная компиляция);
• заменять обозначения параметризованным текстом (макроподстановки).
Определены следующие препроцессорные директивы: #define #include #undef #if #ifdef #else #endif #elif #line #error # ## Указание компилятору: #pragma 10.2.
Замены в тексте Формат: #define <идентификатор> [<текст>] Директива может располагаться в любом месте обрабатываемого текста, ее действие от точки размещения до конца текста.
Директива определяет идентификатор как препроцессорный (это условие можно далее использовать для условной компиляции).
В результате обработки вхождения идентификатора заменяются текстом, окончание которого признак конца строки.
Символы пробела в начале и конце текста в подстановке не участвуют.
Если текст слишком длинный его можно продолжить на другой строке, использую символ «\».
Идентификатор можно переопределять с помощью другого использования #define или отменить его действие с помощью директивы #undef <идентификатор> 10.3.
Макроподстановки Макрос – это средство замены одной последовательности символов другой (замена в тексте простейшая форма макроса).
Большими возможностями обладают макроопределения с параметрами.
Формат: #define <идентификатор>(<список_параметров>) <текст> Примеры: #define max(a, b) a<b?b:a Вхождение в программу max(x, 10) заменяется на x<10? 10:x #define abs(x) x>=0?x:-x Вхождение в программу abs(a) заменяется на a>=0?a:-a Отличие макросов от функций 1.Функции имеют код (за исключением inline- функций) в одном экземпляре, а коды макроса вставляются в программу столько раз сколько используется макрос, причем подстановка для макроса осуществляется всегда.
2.Функции работают с определенными типами параметров, макрос пригоден для обработки параметров любого типа, допустимых в выражении строки замещения.
Механизм перегрузки и шаблоны функций в Си++ позволяют решать те же задачи.
10.4.
Включение текстов из файлов Формат: #include “путь_к_файлу” #include <путь_к_файлу> Включает текст файла в текущий компилируемый файл, когда используются “” файл в первую очередь ищется в текущем каталоге, а затем в системных, а когда <>, то файл ищется в первую очередь в системных каталогах, а затем в текущем.
10.5.
Условная компиляция 1-ая форма: #if <конст_выражение1> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif 2-ая форма #ifdef <идентификатор> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif 3 форма #ifndef <идентификатор> [<текст>] [#elif <конст_выражение2> <текст>] [#elif <конст_выражение3> <текст>] …..
[#else <текст>] #endif Вместо директив #ifdef и #ifndef можно использовать более старые формы: #if defined(<идентификатор>) #if !defined(<идентификатор>) defined(<идентификатор>) – может использоваться в качестве ограниченного константного выражения, например, после #elif Директивы условной компиляции могут использоваться для отладочных печатей, для защиты заголовочных файлов от повторного включения, а также для повышения переносимости программ.
10.6.
Директива нумерации строк #line <константа> [“имя_файла”] Директива сообщает компилятору об изменении имени файла и порядка нумерации строк (следующая строка имеет номер константа+1).
Влияет на диагностические сообщения компилятора.
10.7.
Директива обработки ошибок Формат: #error <текст> Происходит печать текста, как правило, используется совместно с директивами условной компиляции.
Препроцессор прерывает компиляцию и выдает сообщение.
10.8.
Директивы # и ## Для повышения читабельности программ может использоваться пустая директива, состоящая из строки с символом #.
Кроме того, символ # может помещаться перед аргументом в строке текста макроопределения и указывает на необходимость его преобразования с символьную строку (помещается в “ “).
Директива ## используется в строке замещения в макроопределениях для склейки лексем.
10.9.
Заранее определенные препроцессорные идентификаторы __TIME__ __DATE__ __FILE__ __LINE__ _WIN32 _M_IX86 // Определяет используемый процессор __cplusplus _DLL UNICODE и др.
10.10.
Указания компилятору #pragma <последовательность_символов> Определяет зависящие от реализации указания компилятору (прагмы).
Компилятор Visual C++ поддерживает следующие прагмы: alloc text, comment, optimize, auto_inline, component, inline_depth, pack, bss seg, data_seg, function, intrinsic, setlocale, code_seg, hdrstop, message, const seg, once, warning, inline recursion, check_stack, include_alias Например,директива #pragma warning(disable: 4305) предписывает компилятору не выдавать предупреждения при несовпадении типов данных #pragma inline
programming