Многофайловые проекты. Время жизни и область видимости переменных

Метки. Безусловный переход

Директивы препроцессора

Есть специальные команды, которые не компилируются, а лишь указывают препроцессору на необходимость выполнения некоторых действий. Директивы начинаются с символа #.

#include <имя_файла> - добавить в данное место содержимое файла, файл содержится в специальном каталоге подключаемых файлов;

#include "имя_файла" — аналогично #include<…>, но для файла из текущего каталога.

#define идентификатор [строка_замещения] - заменяет все идентификаторы от директивы до конца файла на строку замещения.

Есть модификация данной директивы, позволяющая определять макро-функции:

#define идентификатор (список_аргументов) строка_замещения

#define WIDTH 80

#define LENGTH (WIDTH + 10) //скобки необходимы для сохранения приоритета после замены

#define test(f1, f2) (f1 * f2) //пример определения макро-функции

В макро подстановках могут быть использованы специальные символы и функции:

# — преобразует аргумент в константную строку (заключает аргумент в двойные кавычки)

## — «склеивает» строки

#undef идентификатор - отменяет директиву define, после данной директивы замен не производится.

#if константное_выражение, #elif константное_выражение, #else, #endif предназначены для условной компиляции.

В директиве #if может быть использована функция defined(имя_макроидентификатора), возвращающая 1, если макроподстановка с заданным именем определена, и 0 в противном случае.

Пример:

#if WIDTH > 50 //WIDTH должен быть определен как макрос

… // будет скомпилировано, только если WIDTH > 50

#elif defined(WIDTH)

… //будет скомпилировано, если WIDTH был определен, //но предыдущее условие не выполнено

#endif //конец участка условной компиляции

… // будет скомпилировано независимо от условий

#ifdef, #ifndef — директивы являются аналогом #if defined, #if!defined.

Идентификатор с последующим двоеточием является меткой. Метка является адресом оператора, следующего за меткой. Используется в операторах switch и goto. Областью видимости метки является функция, то есть переход может быть осуществлен только внутри функции, а в разных функциях имена меток могут повторяться. Более того, метки имеют независимое пространство имен, то есть имя метки может повторять имя другого объекта, при этом компилятор их будет различать.

Пример:

int s=0, i=0;

l1: s+=i++;

if (i<100) goto l1;

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

В языке С загружаемая и исполняемая программа называется модулем. Модуль —самая крупная часть программы. Компилятор оформляет модуль в виде четырех сегментов — сегмента кода (text в англоязычной литературе), сегментов данных (data), стека (stack) и динамического сегмента (extend). Каждый сегмент представляет собой непрерывную область памяти и вместе они образуют виртуальное адресное пространство процесса. В оперативной памяти ЭВМ сегменты могут располагаться не связанно друг с другом, что облегчает для ОС организацию мультипрограммного режима работы. Размеры сегментов и способы адресации данных внутри них определяются компилятором на основании так называемых моделей памяти, задаваемых программистом при компиляции.

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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: