Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PYaVU_s.doc
Скачиваний:
44
Добавлен:
24.02.2016
Размер:
665.09 Кб
Скачать
    1. Поименованные константы и макросы

Директива #define обычно используется для связи мнемоничных идентификаторов с константами, ключевыми словами, операторами и выражениями, которые часто используются. Идендтификаторы, которые представляют константы, называются поименованными константами. Идентификаторы, которые представляют операторы или выражения, называются макросами.

Идентификатор не может быть переопределен без отмены первого определения. Однако, идентификатор может быть переопределен точно таким же определением. Таким образом в программе допускается повторение одного и того же определения.

Директива #undef отменяет определение идентификатора. Когда определение отменено, то идентификатор может быть сопоставлен с другим значением. Макросы могут быть определены по образу и подобию с вызовами функций. Поскольку макросы не вырабатывают действительных вызовов функций, то замена вызовов функций макросами может повысить скорость выполнения программы. Однако макросы создают проблемы, если они тщательно не определены. Макро-определения с аргументами могут потребовать использования круглых скобок для определения старшинства операций в выражениях. Макросы могут некорректно повлиять на выражения с побочными эфектами.

      1. Директива # define

Синтаксис:

#define <identifier><text>

#define <identifier>(<parameter-list>)<text>

Директива #define заменяет все вхождения идентификатора <identifier> в исходной программе на <text>, определенный в директиве справа от идентификатора. Идентификатор заменяется, если он оформлен в виде лексемы. Например, идентификатор не изменяется, если он представлен внутри строки или как часть более длинного идентификатора. Если после идентификатора следует список параметров <parameter-list>, то директива #define заменяет каждое вхождение выражения <identifier> (parameter-list) на <text>, модифицированный заменой формальных аргументов фактическими.

<text> представляет собой набор лексем, таких как ключевые слова, константы или составные операторы. Один или более пробельных символов могут разделять <text> от <identifier> (или от заключенных в скобки параметров). Если текст больше чем одна строка, то он может быть продолжен на следующей строке посредством печати символа новой строки с последующей наклонной чертой влево.

<text> может быть опущен. В этом случае все представители идентификатора <identifier> будут удалены из исходного текста программы. Тем не менее, <identifier> рассматривается как определенный и принимает значение 1, если проверяется директивой #if.

Когда задан список параметров <parameter-list>, то он содержит один или более формальных параметров, разделенных запятыми. Каждое имя в списке должно быть уникальным и список должен быть заключен в круглые скобки. Не допускаются пробелы между <identifier> и открывающей скобкой. Имена формальных параметров в тексте <text> отмечают места, куда должны быть подставлены фактические значения. Каждое имя формального параметра может появиться в тексте более одного раза в любом порядке.

Фактические аргументы, следующие непосредственно за идентификатором <identifier> в исходном файле, соответствуют формальным параметрам списка параметров <parameter-list> и модифицируют <text> путем замены каждого формального параметра на соответствующий фактический. Списки фактических и формальных параметров должны содержать одно и то же число аргументов.

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

Примеры:

/*.....* example 1 *.....*/

#define WIDTH 80

#define LENGTH (WIDTH + 10)

/*.....* example 2 *.....*/

#define FILEMESSAGE "Attempt too create file \

failed because of insufficient space"

/*.....* example 3 *.....*/

#define REG1 register

#define REG2 register

#define REG3

/*.....* example 4 *.....*/

#define MAX(x,y) ((x) > (y)) ? (x) : (y)

/*.....* example 5 *.....*/

#define MULT (a,b) ((a) * (b))

В первом примере определяется идентификатор WIDTH, как целая константа 80, и определяется идентификатор LENGTH, как (WIDTH + 10). Каждое вхождение LENGTH заменяется на (WIDTH + 10), которое в свою очередь заменяется на выражение (80 + 10). Скобки являются важными, поскольку они управляют интерпретацией в операторах, подобных следующему:

var = LENGTH * 20;

После препроцессирования оператор будет таким:

var = (80 + 10) * 20;

Значение, которое присваивается, равно 1800. Без скобок значение 80+10*20 равнялось бы 280.

Во втором примере определяется идентификатор FILEMESSAGE. Определение продолжается на вторую строку путем использования символа "\".

В третьем примере определены три идентификатора, REG1, REG2, REG3. REG1 и REG2 определены как ключевые слова register. Определение REG3 опущено и, таким образом, любое вхождение REG3 будет удалено из исходного файла. Эти директивы могут быть использованы для того, чтобы обеспечить наиболее важным переменным программы (заданным с REG1 и REG2) задание класса памяти register.

В четвертом примере дано макроопределение, поименованное MAX. Каждое текущее вхождение макро-вызова MAX в исходном файле заменяется выражением ((x)>(y))?(x):(y), в котором формальные параметры x и y заменяются на фактические. Например, вхождение

MAX(1,2)

заменяется на

((1)>(2)?(1):(2),

а вхождение

MAX (i, s[i])

заменяется на

((i)>(s[i]))?(i):(s[i])

Макро-вызов проще читать, чем соответствующее выражение, которое подставляется. Исходная программа становится проще для понимания.

Заметим, что в этом макро аргументы с побочными эффектами могут быть причиной непредсказуемых результатов.

Например, макро-вызов MAX (i,s[i++]) заменится на

((i)>(s[i++]))?(i):(s[i++])

Выражение s[i++] вычисляется дважды. Результат тернарного выражения неопределен, т.к. его операторы могут быть вычислены в любом порядке, а значение переменной i зависит от порядка вычисления.

В пятом примере определяется макро с именем MULT. Макровызов MULT (3,5) в тексте программы заменяется на (3)*(5). Круглые скобки, в которые заключаются фактические параметры, важны, поскольку они управляют интерпретацией составных аргументов. Например, макровызов MULT (3+4,5+6) заменится на (3+4)*(5+6), что эквивалентно 76. Без скобок результат подстановки 3+4*5+6 равен 29.