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

Автор: Пользователь скрыл имя, 02 Декабря 2011 в 09:03, реферат

Описание работы

Хотя Turbo C++ использует использует интегрированный однопроходный компилятор как при работе в интегрированной среде разработки (IDE), так и при вызове компилятора из командной строки, полезно тем не менее сохранить терминологию, сохранившуюся от более ранних, многопроходных компиляторов. В случае последних на первом проходе обработки исходного текста программы выполняется подключение всех имеющихсявключаемых файлов, проверка всех условных директив компиляции, расширение всех имеющихся макросов и получение промежуточного файла для обработки последующими проходами компилятора. Посколькукак интегрированная среда разработки, так и версия командной строки Turbo C++ выполняют первый проход, не создаваяпри этом каких-либо промежуточных файлов, Turbo C++ включаетв себя независимый препроцессор, CPP.EXE, который имеет на выходе такой промежуточный файл. CPP полезен на стадии отладки, посколькупоказывает в чистом виде результаты работы директив включения, условных директив компиляции и сложных макрорасширений.

Работа содержит 1 файл

Директивы препроцессора Turbo C.docx

— 48.44 Кб (Скачать)

   Условная  компиляция

   Turbo C++ поддерживаетусловную компиляцию путем замены соответствующих строк исходного кода пустой строкой. Игнорируемые таким образом строки это те строки, что начинаются с символа # (за исключением директив #if, #ifdef, #ifndef, #else, #elif и #endif), а также любые строки, которые в результате выполнения директив не должны компилироваться. Все директивы условной компиляции должны завершаться в том же исходном или включаемом файле, где находится их начало.

   Директивы условной компиляции #if, #elif, #else и #endif

   Директивы условной компиляции #if, #elif, #else и #endif работают аналогично обыкновенным условным операторам

   С.Они  используются следующим образом:

   #if выражение-1-типа-константы

   <раздел-1>

   <#elif выражение-2-типа-константы новая-строка раздел-2>

   ...

   <#elif выражение-n-типа-константы новая-строка раздел-n>

   <#else последний-раздел>

   #endif

   ...

   Если  выражение-1-типа-константы(для котороговыполняется макрорасширение) дает ненулевое значение (истина), то строки кода (возможно, пустые), представленногоразделом-1, которые могут представлять собой как командные строки препроцессора, так и обычные строки исходного кода, обрабатываются препроцессором и соответствующим образом передаются компилятору Turbo C++. В противном случае, если выражение-1-типа-константы дает нулевое значение (ложь), раздел-1игнорируется (макрорасширение и компиляция данного раздела не выполняются).

   В случае "истина" после обработки  раздела-1 препроцессором управление передается соответствующейдирективе #endif (которая заканчивает даннуюусловную конструкцию) и продолжается в следующем-разделе. В случае "ложь" управление передается следующей строке #elif (если она определена в данной конструкции),где вычисляетсявыражение-2-типа-константы. В случае "истины" обрабатывается раздел-2, после чего управление передается соответствующей директиве #endif, и т.д.,до тех пор, пока не будет достигнута последняя директива #else или #endif. Опциональная директива #else используется в качестве альтернативного условия в том случае, если все предыдущие проверки дали значение "ложь". Последовательность условных директив заканчивается директивой #endif.

   Обработанный  препроцессором раздел может в свою очередь содержать вложенные  на любую глубину условные предложения, причем каждой директиве #if должна соответствовать закрывающая директива #endif.

   Итоговым  результатом вышеописанного сценария является то, что для дальнейшей обработки передается только один раздел (возможно, пустой). Опущенныеразделы служат только для отслеживания возможных вложенных условных конструкций, так что каждая директива #if должна обязательно иметь соответствующую ейзавершающую директиву #endif.

   Проверяемые выражения-типа-константы при вычислении должны давать целочисленную константу.

   Операция  defined

   Операция  defined дает альтернативный, более гибкий способ проверки того, определены ли комбинации идентификаторов, или нет. Данная операция допустима только в выражениях #if и #elif.

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

   #if defined(mysym)

   это то же, что

   #ifdef mysym

   Преимущество  заключается в том, что можно  использовать defined циклически в сложном выражении, следующем за директивой #if, например

   #if defined(mysym) && !defined(yoursym)

   Условные  директивы #ifdef и #ifndef

   Условные  директивы #ifdef и #ifndef позволяют проверить, определен лив текущий момент данный идентификатор, то есть была ли обработана предыдущаядиректива #define для данного идентификатора и продолжает ли она действовать в текущий момент.

   Строка

   #ifdef идентификатор

   имеет точно такой же эффект, что и 

   #if 1

   если  идентификатор в текущий момент определен, и такой же эффект, что  и

   #if 0

   если  идентификатор в текущий момент не определен.

   #ifndef, напротив, дает значение "истина", если идентификатор "не определен", поэтому строка

   #ifndef идентификатор

   имеет точно такой же эффект, что и

   #if 0

   если  идентификатор в текущий момент определен, и такой же эффект, что  и

   #if 1

   если  идентификатор в текущий момент не определен.

   Синтаксис следует синтаксису директив #if, #elif, #else и #endif, описанному в предыдущем разделе.

   Идентификатор, определенный как имеющий пустое (NULL) значение, считается определенным.

   Директива управления нумерацией строк #line

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

   #line целочисленная-константа <"имя-файла">

   и обозначает, что следующая исходная строка берется начиная с номера строки, заданного целочисленной-константой, из файла, заданного "именем-файла". После того, как имя-файла было однажды задано, все последующие команды #line, относящиеся к данному файлу, может опустить явный аргумент имя-файла. Например,

   /* TEMP.C: пример директивы #line  */

   #include <stdio.h>

   #line 4 "junk.c"

   void main()

   (*

   printf(" in line %d of %s",__LINE__,__FILE__);

   #line 12 "temp.c"

   printf("\n");

   printf(" in line %d of %s",__LINE__,__FILE__);

   #line 8

   printf("\n");

   printf(" in line %d of %s",__LINE__,__FILE__);

   *)

   Включение stdio.h означает, что на выходе препроцессора будет нечто большее.

   Если  запустить TEMP.C через CPP (cpp temp), то на выходе получится файл TEMP.I, который выглядит так:

   temp.c 1:

   c:\borland\tc\cpp\include\stdio.h 1:

   c:\borland\tc\cpp\include\stdio.h 2:

   c:\borland\tc\cpp\include\stdio.h 3:

   ...

   c:\borland\tc\cpp\include\stdio.h 212:

   c:\borland\tc\cpp\include\stdio.h 213:

   temp.c 2:

   temp.c 3:

   junk.c 4: void main()

   junk.c 5: (*

   junk.c 6: printf(" in line %d of %s",6,"junk.c");

   junk.c 7:

   temp.c 12: printf("\n");

   temp.c 13: printf(" in line %d of %s",13,"temp.c");

   temp.c 14:

   temp.c 8: printf("\n");

   temp.c 9: printf(" in line %d of %s",9,"temp.c");

   temp.c 10: *)

   temp.c 11:

   Если  вызатем компилируете TEMP.C, то получится следующий выход:

   in line 6 of junk.c

   in line 13 of temp.c

   in line 9 of temp.c

   Макросы расширяются в аргументах #line, как в директивах #include.

   Прежде  всего назначение директивы #line заключается в использовании ее в утилитах, имеющих на выходе коды С, а не в кодах, создаваемых человеком "вручную".

   Директива #error

   Директива #error имеет следующий синтаксис:

   #error сообщение-об-ошибке

   Директива генерирует сообщение:

   Error: имя-файла номер-строки : Error directive: сообщение

   Данная  директива обычно встраивается в  условные конструкции препроцессора, которые отслеживают какие-либо нежелательные условия времени  компиляции.Обычноэто условие "ложно". Если условие "истинно", то компилятор может выдать сообщение об ошибке и прекратитьработу. Для этого директива# error помещается в условную ветвь, которая дает для искомого нежелательного условия результат "истина".

   Например, вы определили #define MYVAL, принимающую значения 0 или 1. Затем можновключить в исходный код условную директиву, которая будет проверять MYVAL на предмет неверного значения:

   #if (MYVAL != 0 && MYVAL != 1)

   #error MYVAL must be defined to either 0 or 1

   #endif

   Директива #pragma

   Директива #pragma позволяет использовать специфичные для конкретных реализаций директивы в форме

   #pragma имя-директивы

   При помощи #pragma Turbo C++позволяет определить любые желаемые директивы, не обращаясь дляэтогок другим, поддерживающим их компиляторам. Если компилятор не поддерживает данное имя-директивы, то он просто игнорируетдирективу #pragma, не выдаваяпри этом никаких сообщений об ошибкахили предупреждений.

   Turbo C++ поддерживает следующие директивы #pragma:

   - #pragma argsused

   - #pragma exit

   - #pragma inline

   - #pragma option

   - #pragma saveregs

   - #pragma startup

   - #pragma warn

   Директива #pragma argsused

   Директива #pragma argsused допустима только между определениями функций и действует только на следующую функцию. Она отменяет сообщение уровня предупреждения:

   "Parameter name is never used in function имя-функции" ("имя параметра нигде не используется в функции имя-функции")

   Директивы #pragma exit и #pagma startup

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

   Синтаксис этих директив следующий:

   #pragma exit имя-функции <приоритет>

   #pragma startup имя-функции <приоритет>

   Заданное  имя-функции должно относиться к ранееобъявленной функции, не принимающей аргументов и возвращающей значение void; другими словами, эта функция должна быть объявлена как:

   void func(void);

   Опциональный  параметр приоритет должен являться целым числом в диапазоне от 64 до 255. Старшим приоритетом является 0. (Приоритеты от 0 до 63 используются библиотеками С и не должны использоваться пользователем). Функции со старшими приоритетами вызываются первыми при загрузке программы и последними при выходе из нее. Если приоритет не задан, то по умолчанию он равен 100. Например,

   #include <stdio.h>

   void startFunc(void)

   (*

   printf("Startup function.\n");

   *)

   #pragma startup startFunc 64

   /* приоритет  64 --> вызывается при загрузке  первой */

   void exitFunc(void)

   (*

   printf("Wrapping up execution.\n");

   *)

   #pragma exit exitFunc

   /* приоритет  по умолчанию равен 100 */

   void main(void)

   (*

   printf(This is main.\n");

   *)

Информация о работе Директивы процессора в С++