Автор: Пользователь скрыл имя, 02 Декабря 2011 в 09:03, реферат
Хотя Turbo C++ использует использует интегрированный однопроходный компилятор как при работе в интегрированной среде разработки (IDE), так и при вызове компилятора из командной строки, полезно тем не менее сохранить терминологию, сохранившуюся от более ранних, многопроходных компиляторов. В случае последних на первом проходе обработки исходного текста программы выполняется подключение всех имеющихсявключаемых файлов, проверка всех условных директив компиляции, расширение всех имеющихся макросов и получение промежуточного файла для обработки последующими проходами компилятора. Посколькукак интегрированная среда разработки, так и версия командной строки Turbo C++ выполняют первый проход, не создаваяпри этом каких-либо промежуточных файлов, Turbo C++ включаетв себя независимый препроцессор, CPP.EXE, который имеет на выходе такой промежуточный файл. CPP полезен на стадии отладки, посколькупоказывает в чистом виде результаты работы директив включения, условных директив компиляции и сложных макрорасширений.
Условная компиляция
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-типа-
Обработанный препроцессором раздел может в свою очередь содержать вложенные на любую глубину условные предложения, причем каждой директиве #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\
c:\borland\tc\cpp\include\
c:\borland\tc\cpp\include\
...
c:\borland\tc\cpp\include\
c:\borland\tc\cpp\include\
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
Данные
две директивы позволяют
Синтаксис этих директив следующий:
#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");
*)