Реферат Курсовая Конспект
Лекция 17 - Лекция, раздел Информатика, Лекция 17 Препроцессор Языка C ...
|
Препроцессор языка C
Препроцессор языка C – это программа, выполняющая обработку исходного кода для передачи его компилятору, в процессе которой происходит подстановка директив и выполнение операций препроцессора. Все директивы препроцессора начинаются с символа ‘#’ и могут находиться в любом месте программы.
Конcтaнтныe выpaжeния, иcпoльзуeмыe в диpeктивax пpeпpoцeccopa, имeют дoпoлнитeльныe oгpaничeния, пoэтoму нaзывaютcя oгpaничeнными кoнcтaнтными выpaжeниями. Oгpaничeнныe кoнcтaнтныe выpaжeния нe мoгут coдeжaть выражений с операцией sizeof, кoнcтaнт пepeчиcлимого типа или выpaжeний явного преобразования типa.
Директивы #define и #undef.
Директива #define вводит макроопределение (макрос). Форма записи:
#define имя последовательность_символов
Поле имя задаёт имя макроса, которое как правило пишется заглавными буквами. Поле последовательность_символов является строкой замещения имени. Между этими полями должен быть хотя бы один пробел. Когда препроцессор находит в тексте программы имя, он заменяет его на последовательность_символов (производит макрорасширение).
Наиболее часто макросы используют для определения целочисленных констант. В качестве макроса может использоваться строковая константа, если она не помещается на одну строку, то для переноса можно использовать символ ‘’
Пример 1
#define STRING “Эта строковая константа
не умещается на одной строке”
Макрос может иметь параметры. Форма записи:
#define имя(список_формальных_параметров) последовательность_символов
Поле список_формальных_параметров содержит формальные параметры макроса, имена которых могут быть использованы в поле последовательность_символов. Подобные макросы при использовании в тексте программы должны содержать в скобках списки фактических параметров, которые будут использоваться при макрорасширении.
Макросы могут быть вложенными, когда поле последовательность_символов содержит в себе имя другого, ранее определенного макроса.
Пример 2
#define PI 3.14159
#define SQUARE(a) a*a
#define AREA(b) PI*SQUARE(b)
…
float a=AREA(2.5);
Директива #undef отменяет макроопределение начиная с того места в тексте программы, где находится эта директива. Для всех макросов, определённых и использованных в тексте программы до их отмены, будут проведены макрорасширения. Если при объявлении макрос имеет параметры, а при отмене указывается без параметров, то он всё равно будет отменён, важно, чтобы совпадало поле имя. Форма записи:
#undef имя
Пример 3
#define N 10
…
#undef N
Операция «преобразование в строку».
Параметр макроса в поле последовательность_символов может быть преобразован в строку символов в результате выполнения операции «преобразование в строку». Как и любая строка, результат операции объединяется с другими строками, если разделён от них лишь пробелами. Форма записи:
# параметр_макроса
Поле параметр макроса должно содержать параметр макроса. Если это поле не содержит параметр макроса, то препроцессор будет считать данную форму записи простой последовательностью символов, а не операцией.
Пример 4
#define M1(var) printf("var#=%d ",var)
#define M2(var) printf(#var"=%d ",var)
…
M1(4);
M2(2);
На экране будет напечатано: var#=4 2=2
Операция «склейка лексем».
Операция «склейка лексем» объединяет в одну две лексемы, между которыми она находится. Новая лексема проверяется на предмет возможного расширения. Форма записи:
лексема1##лексема2
Поля лексема1 и лексема2 содержат лексемы. Результатом будет новая лексема, состоящая из этих двух лексем.
Пример 5
#define DEF_VAR1(n) int var##n
#define USE_VAR1(n) var##n
#define SHW_VAR1(n) printf("var"#n"=%d",var##n)
…
DEF_VAR1(1);
USE_VAR1(1)=2;
SHW_VAR1(1);
На экране будет напечатано: var1=2
Директива #include.
Директива подключает к исходному коду заданный в директиве файл. При подключении содержимое подключаемого файла полностью копируется в исходный файл с той позиции, где находится директива. Формы записи
#include <имя_файла>
#include “имя_файла”
#include имя_макроса
Поле имя_файла содержит имя подключаемого файла. Если имя файла не является полным именем, то для первой формы записи поиск производится только в пределах системных каталогов, на которые настроена среда программирования, а для второй формы записи поиск будет производиться сначала в текущем каталоге, а затем и в системных каталогах, как и в первом случае. Первая форма записи используется для подключения заголовочных файлов стандартных библиотек, вторая форма записи – для подключения файлов, создаваемых пользователем.
Поле имя_макроса содержит имя макроса, первый символ которого не должен быть ‘<’ или ‘”’. Для данной формы записи предполагается, что существует макрос, в результате макрорасширения которого получится либо <имя_файла>, либо “имя_файла”.
Если файл не будет найден, то система выдаст сообщение об ошибке.
Пример 6
#include <stdio.h>
#include “Unit1.h”
Директивы #if, #else, #elif, #endif, #ifdef, #ifndef.
Эти директивы позволяют выполнять условную компиляцию участков исходного кода, возможно вложенное использование директив. Существуют три набора директив условной компиляции: набор #if, #endif; набор #ifdef, #endif; набор #ifndef, #endif.
Набор #if, #endif.
Форма записи:
#if выражение1
участок кода1 // Компилируется, если выражение1 «истинно»
#elif выражение2
участок кода2 // Компилируется, если выражение2 «истинно» и
// выражение1 «ложно»
#elif выражение3
участок кода3 // Компилируется, если выражение3 «истинно», а
// выражение1 и выражение2 «ложно»
…
#elif выражениеN
участок кодаN // Компилируется, если выражениеN «истинно», а
// выражение1, выражение2, выражение3, … «ложно»
#else
участок кодаN+1 // Компилируется, если выражение1, выражение2,
//выражение3, …, выражениеN «ложно»
#endif
Поля выражение1, …, выражениеN содержат выражения, включающие в себя константы или макросы, запрещается использование переменных (значения выражений должны быть известны на этапе обработки препроцессором). Поля участок кода1, …, участок кодаN содержат участки кода исходной программы.
Директива #if используется с директивой #endif и воздействует на участок кода, заключённый между ними. Директива #elif используется внутри директив #if и #endif для организации вложенных условий компиляции и проверяется в том случае, если значения выражений директивы #if и всех предшествующих ей директив #elif приняли значение «ложно». Директива #else используется внутри директив #if и #endif для выделения участка кода, который будет компилироваться, если значения выражений директивы #if и всех предшествующих ей директив #elif приняли значение «ложно».
Для данного набора директив действуют следующие правила:
- для каждой директивы #if должна присутствовать соответствующая директива #endif;
- директивы #elif и #else являются необязательными;
- число директив #elif не ограничено;
- директива #else должна быть одна и после неё не должно быть директив #elif.
Оператор defined().
Оператор defined() применяется в выражениях директив #if и #elif и позволяет проверить, определён ли макрос. Форма записи:
defined(имя)
Поле имя содержит имя макроса. Оператор принимает значение «истинно», если макрос определён, и значение «ложно» в противном случае.
Набор #ifdef, #endif.
Форма записи:
#ifdef имя
участок кода1 // Компилируется, если имя определено
#else
участок кода2 // Компилируется, если имя не определено
#endif
Поле имя содержит имя макроса. Фактически действие директивы
#ifdef имя
аналогично действию директивы
#if defined(имя)
Набор #ifndef, #endif.
Форма записи:
#ifndef имя
участок кода1 // Компилируется, если имя не определено
#else
участок кода2 // Компилируется, если имя определено
#endif
Поле имя содержит имя макроса. Фактически действие директивы
#ifndef имя
аналогично действию директивы
#if !defined(имя)
Внутри наборов #ifdef, #endif и #ifndef, #endif нельзя использовать директиву #elif. Использование директивы #else является необязательным.
Директива #error.
Эта директива прекращает компиляцию программы и выдаёт сообщение об ошибке. Обычно встраивается в условные директивы препроцессора. Форма записи:
#error сообщение
Поле сообщение содержит сообщение об ошибке
Директива #line.
Директива #line используется для изменения внутреннего счётчика строк компилятора (макрос __LINE__) и имени файла (макрос __FILE__). Форма записи:
#line номер_строки «имя_файла»
Поле номер_строки определяет новый номер строки и должно быть целой константой. Поле имя_файла является необязательным, заключается в двойные кавычки и содержит новое имя файла. Данная директива игнорируется в интегрированной среде разработки, но может быть использована при компиляции из командной строки.
Пример 7
#line 10 «new.cpp»
Нуль-директива.
Это пустая директива. Форма записи:
#
Директива #pragma.
Позволяет управлять специфическими возможностями компилятора. Форма записи:
#pragma имя_директивы
Поле имя_директивы содержит значение директивы #pragma из набора директив, определённых для данного компилятора. Данный набор зависит от конкретной реализации компилятора. Если компилятор не поддерживает данное имя директивы, то оно просто игнорируется. Ниже в таблице приведены директивы для среды разработки Borland C++ 3.1 и их описание.
Директива | Описание |
argused | Подавляет предупреждающее сообщение "Parameter ‘parameter’ is never used" |
exit | Указывает функцию, вызываемую перед завершением программы |
hdrfile | Задает имя прекомпилируемого заголовочного файла |
hdrstop | Предписывает компилятору не включать дальнейшую информацию в прекомпилируемый заголовочный файл |
intrinsic | Командный переключатель встраиваемых функций |
inline | Компиляция текущего модуля должна производиться через ассемблер (компилятор переводит исходный код в код ассемблера и затем вызывает ассемблер для создания объектного файла) |
option | Позволяет включать в код опции командной строки компилятора |
saveregs | Гарантирует, что дальняя функция не изменит значение какого-либо регистра при вызове |
startup | Указывает функцию, которая должна выполняться при загрузке программы перед функцией main() |
warn | Позволяет выборочно разрешать или подавлять предупреждающие сообщения |
Предопределённые макросы.
Предопределённые макросы определяются средой разработки независимо от программиста и являются доступными в программе. Стандарт ANSI языка C определяет 5 таких макросов, которые приведены в таблице ниже.
Макрос | Описание |
__DATE__ | Строка, представляющая в форме месяц/день/год дату, когда файл обрабатывался препроцессором |
__FILE__ | Строка, содержащая имя файла в двойных кавычках |
__LINE__ | Текущий номер строки исходного файла |
__STDC__ | Имеет значение 1, если установлена совместимость компилятора со стандартом ANSI, в противном случае макрос не определён |
__TIME__ | Строка, представляющая в форме часы:минуты:секунды время, когда файл обрабатывался препроцессором |
Кроме этих макросов в среде разработки могут быть использованы другие предопределённые макросы. Ниже в таблицах приведены предопределённые макросы для среды разработки Borland C++ 3.1 и их описание.
Макрос | Описание |
__TINY__ | Определён, если используется модель TINY |
__SMALL__ | Определён, если используется модель SMALL |
__COMPACT__ | Определён, если используется модель COMPACT |
__MEDIUM__ | Определён, если используется модель MEDIUM |
__LARGE__ | Определён, если используется модель LARGE |
__HUGE__ | Определён, если используется модель HUGE |
_Windows | Определён, если компилируется Windows-приложение |
Макрос | Значение | Описание |
__BCPLUSPLUS__ | 0x0310 | Определён, если выбран режим компиляции C++ |
__BORLANDC__ | 0x0410 | Номер версии |
__CDECL__ | Определён, если используется вызов функций по правилам языка C | |
__cplusplus | Определён, если выбран режим C++ | |
__DLL__ | Определён, если компилируется DLL | |
__MSDOS__ | Целая константа | |
__OVERLAY__ | Определён, если установлена опция компилятора -Y | |
__PASCAL__ | Определён, если используется вызов функций по правилам языка Pascal | |
__TCPLUSPLUS__ | 0x0310 | Номер версии |
__TURBOC__ | 0x0410 | Определён для совместимости со старыми программами |
– Конец работы –
Эта тема принадлежит разделу:
На сайте allrefs.net читайте: Лекция 17.
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Лекция 17
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов