Директивы препроцессора
При каждом запуске компилятора сначала запускается препроцессор, который выполняет директивы начинающиеся с символа #. При выполнении этих команд создается временный файл исходного кода, с которым уже работает компилятор.
Директива #include
Строка
#include "имя файла"
Заменяет эту строку полным содержимым файла имя. файла. Если не указан путь то файл сначала ищется в директории исходного файла , затем в директории заданной в опциях компилятора(обычно директория Include).
Строка #include <имя файла>
Ищет файл только в директории заданной в опциях компилятора.
Директива #define
#define идентификатор строка символов
Заменяет все последующие вхождения идентификатора строкой символов. Пример:
#define A_NUMBER 100
int n=A_NUMBER;
n присвоится значение 100
#define можно применять также для определения макросов, например:
#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp
Подробнее о #define (и в частности о макросах) будет отдельная статья.
Директива #undef
#undef идентификатор
Отменяет прероцессорное определение идентификатора.
Директивы #if #else #endif
#if выражение
.....
#endif
Проверяет истинно ли выражение и если истинно, то выполняет все последующие строки до директивы #endif.
Конструкция типа:
#if выражение
....
#else
...
#endif Проверяет выражение, если оно истинно то выполняются строки между #if и #else а если ложно то между #else и #endif.
Директивы #ifdef #ifndef
#ifdef идентификатор
.....
#endif
Проверяет определен ли идентификатор в препроцессоре в данный момент(директивой #define) и если определен, то выполняет все последующие строки до директивы #endif.
#ifndef идентификатор
.....
#endif
Наоборот, выполняет все последующие строки до директивы #endif если идентификатор не определен в препроцессоре в данный момент.
Директива #error
#error - сообщение об ошибке. Останавливает работу компилятора и выдает сообщение об ошибке. Например:
#ifndef smth_important
#error smth important isn't defined
#endif
Компилятор выдаст что-то типа:
Fatal F1003 file.cpp 2: Error directive: smth important isn't defined
*** 1 errors in Compile ***
Директива #line
Директива
#line константа "имя файла"Заставляет компилятор считать, что константа задает номер следующей строки исходного файла, и текущий входной файл именуется идентификатором. Если идентификатор отсутствует, то запомненное имя файла не изменяется.
Директива #pragma
#pragma - это директива препроцессора, которая реализует возможности компилятора. Эти особенности могут быть связанны с типом компилятора.Разные типы компиляторов могут поддерживать разные директивы. Общий вид директивы:
#pragma команда компилятора
Например:
#pragma message("сообщение") - просто выдает сообщение при компиляции.
Области видимости
Функции и внешние переменные, из которых состоит Си-программа, каждый раз компилировать все вместе нет никакой необходимости. Исходный текст можно хранить в нескольких файлах. Ранее скомпилированные программы можно загружать из библиотек. В связи с этим возникают следующие вопросы:
• Как писать объявления, чтобы на протяжении компиляции используемые переменные были должным образом объявлены?
• В каком порядке располагать объявления, чтобы во время загрузки все части программы оказались связаны нужным образом?
• Как организовать объявления, чтобы они имели лишь одну копию?
• Как инициализировать внешние переменные?
Начнем с того, что разобьем программу-калькулятор на несколько файлов. Конечно, эта программа слишком мала, чтобы ее стоило разбивать на файлы, однако разбиение нашей программы позволит продемонстрировать проблемы, возникающие в больших программах.
Областью видимости имени считается часть программы, в которой это имя можно использовать. Для автоматических переменных, объявленных в начале функции, областью видимости является функция, в которой они объявлены. Локальные переменные разных функций, имеющие, однако, одинаковые имена, никак не связаны друг с другом. То же утверждение справедливо и в отношении параметров функции, которые фактически являются локальными переменными.
Область действия внешней переменной или функции простирается от точки программы, где она объявлена, до конца файла, подлежащего компиляции. Например, если main, sp, val, push и pop определены в одном файле в указанном порядке, т. е.
main() {...} int sp = 0;double val[MAXVAL]; void push(double f) {...}double pop(void) {...}то к переменным sp и val можно адресоваться из push и pop просто по их именам; никаких дополнительных объявлений для этого не требуется. Заметим, что в main эти имена не видимы так же, как и сами push и pop.
Однако, если на внешнюю переменную нужно сослаться до того, как она определена, или если она определена в другом файле, то ее объявление должно быть помечено словом extern.
Важно отличать объявление внешней переменной от ее определения. Объявление объявляет свойства переменной (прежде всего ее тип), а определение, кроме того, приводит к выделению для нее памяти. Если строки
int sp;double val[MAXVAL];расположены вне всех функций, то они определяют внешние переменные sp и val, т. e. отводят для них память, и, кроме того, служат объявлениями для остальной части исходного файла. А вот строки
extern int sp;extern double val[];объявляют для оставшейся части файла, что sp - переменная типа int, а val - массив типа double (размер которого определен где-то в другом месте); при этом ни переменная, ни массив не создаются, и память им не отводится.
На всю совокупность файлов, из которых состоит исходная программа, для каждой внешней переменной должно быть одно-единственное определение; другие файлы, чтобы получить доступ к внешней переменной, должны иметь в себе объявление extern. (Впрочем, объявление extern можно поместить и в файл, в котором содержится определение.) В определениях массивов необходимо указывать их размеры, что в объявлениях extern не обязательно. Инициализировать внешнюю переменную можно только в определении. Хотя вряд ли стоит организовывать нашу программу таким образом, но мы определим push и pop в одном файле, а val и sp - в другом, где их и инициализируем. При этом для установления связей понадобятся такие определения и объявления:
В файле 1: extern int sp;extern double val[]; void push(double f) {...}double pop(void) {...}В файле2: int sp = 0;double val[MAXVAL];Поскольку объявления extern находятся в начале файла1 и вне определений функций, их действие распространяется на все функции, причем одного набора объявлений достаточно для всего файла1. Та же организация extern-объявлений необходима и в случае, когда программа состоит из одного файла, но определения sp и val расположены после их использования.
Дата добавления: 2016-04-14; просмотров: 830;