2844

Препроцессор языка C

Контрольная

Информатика, кибернетика и программирование

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

Русский

2012-10-20

75.5 KB

5 чел.

Препроцессор языка 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__

1

Определён, если используется вызов функций по правилам языка C

__cplusplus

1

Определён, если выбран режим C++

__DLL__

1

Определён, если компилируется DLL

__MSDOS__

1

Целая константа

__OVERLAY__

1

Определён, если установлена опция компилятора -Y

__PASCAL__

1

Определён, если используется вызов функций по правилам языка Pascal

__TCPLUSPLUS__

0x0310

Номер версии

__TURBOC__

0x0410

Определён для совместимости со старыми программами


 

А также другие работы, которые могут Вас заинтересовать

29026. Ленточные фундаменты под колонны и их конструктивные решения 26 KB
  Ленточные фундаменты под колонны и их конструктивные решения. Ленточные фундаменты под колонны устраивают в виде одиночных под ряд колонн или перекрёстных под сетку колонн лент рис. Ленточные фундаменты под колонны предают большую жёсткость сооружению и способствуют выравниванию его осадки.
29027. Сплошные фундаменты. Основные конструктивные решения. Сопряжение колонн со сплошными фундаментами 31 KB
  Сплошные фундаменты. Сплошные фундаменты иногда называемые плитными устраивают под всем зданием в виде железобетонных плит под стены или сетку колонн рис. Сплошные фундаменты способствуют уменьшению неравномерности осадки сооружения. Сплошные фундаменты выполняются как правило из монолитного железобетона.
29028. Определение глубины заложения фундамента исходя из инженерно-геологических и гидрогеологических условий строительной площадки 31.5 KB
  Этот выбор производится на основе предварительной оценки прочности и сжимаемости грунтов по геологическим разрезам. Покажем это на примере рассмотрев 3 наиболее характерные схемы напластований грунтов приведенные на рис. Площадка сложена одним или несколькими слоями прочных грунтов при этом строительные свойства каждого последующего слоя не хуже свойств предыдущего. В этом случае глубина заложения фундамента принимается минимальной допускаемой при учёте сезонного промерзания грунтов и конструктивных особенностей сооружения рис.
29029. Учёт глубины сезонного промерзания грунтов при выборе глубины заложения фундаментов зданий и сооружений 20.5 KB
  Учёт глубины сезонного промерзания грунтов при выборе глубины заложения фундаментов зданий и сооружений. Глубина заложения фундамента из условия промерзания грунтов назначается в зависимости от их вида состояния начальной влажности и уровня подземных вод в период промерзания. Как непучинистые рассматриваются также пески мелкие и пылеватые с любой влажностью а также супеси твёрдой консистенции если уровень подземных вод во время промерзания находится от спланированной отметки земли на глубине равной расчётной глубине промерзания плюс 2 м...
29030. Определение глубины заложения фундаментов с учётом конструктивных особенностей сооружения, включая глубину прокладки подземных коммуникаций, наличие и глубину заложения соседних фундаментов 31.5 KB
  Определение глубины заложения фундаментов с учётом конструктивных особенностей сооружения включая глубину прокладки подземных коммуникаций наличие и глубину заложения соседних фундаментов. Основными конструктивными особенностями возводимого сооружения влияющими на глубину заложения его фундамента являются: наличие и размеры подвальных помещений приямков или фундаментов под оборудование; глубина заложения фундаментов примыкающих сооружений; наличие и глубина прокладки подземных коммуникаций. В зданиях с подвалом или полуподвалом а также...
29031. Определение размеров подошвы центрально нагруженных фундаментов мелкого заложения 63.5 KB
  Реактивное давление грунта по подошве жёсткого центрально нагруженного фундамента принимается равномерно распределённым интенсивностью: 1 где NoII расчётная вертикальная нагрузка на уровне обреза фундамента; GfII и GgII расчётные значения веса фундамента и грунта на его уступах см.1; А площадь подошвы фундамента. Площадь подошвы фундамента при его расчёте по второму предельному состоянию по деформациям определяется из условия: pII ≤ R 2 где R расчётное сопротивление грунта основания. Поскольку обе части неравенства 2...
29032. Определение размеров подошвы внецентренно нагруженных фундаментов мелкого заложения. Эпюры давлений под подошвой фундамента. Порядок расчёта 33 KB
  Эпюры давлений под подошвой фундамента. При расчёте давление по подошве внецентренно нагруженного фундамента принимают изменяющимся по линейному закону а его краевые значения при действии момента сил относительно одной из главных осей определяют как для случая внецентренного сжатия по формуле: 1 Подстановкой значений А=l·b W=b2l 6 и M=NII·e формула 1 приводится к виду 2 2 где NII суммарная вертикальная нагрузка на основание включая вес фундамента и грунта на его уступах; A площадь подошвы фундамента; е эксцентриситет...
29033. Гидроизоляция фундаментов. Защита подвальных помещений от сырости и подтопления подземными водами 42 KB
  Гидроизоляция фундаментов. Гидроизоляция предназначается для обеспечения водонепроницаемости сооружений антифильтрационная гидроизоляция а также защиты от коррозии и разрушения материалов фундаментов и подземных конструкций от агрессивных подземных вод антикоррозионная гидроизоляция. Гидроизоляция от сырости и грунтовых вод подвальных и заглубленных помещений является значительно более сложной выбор такой гидроизоляции зависит от гидрогеологических условий строительной площадки уровня подземных вод их агрессивности особенностей...
29034. Расчёт фундаментов по второй группе предельных состояний. Определение конечной осадки фундаментов мелкого заложения методом послойного суммирования 34 KB
  Расчёт оснований фундаментов по второй группе предельных состояний по деформациям производится исходя из условия: s ≤ su 1 где s конечная стабилизированная осадка фундамента определённая расчётом; su предельное значение осадки устанавливаемое соответствующими нормативными документами или требованиями проекта. После определения размеров подошвы фундамента и проверки условия pII ≤ R где рII среднее давление на основание по подошве фундамента a R расчётное сопротивление грунта ось фундамента совмещают с литологической колонкой...