С и С++ включват няколко предпроцесорни директиви които се използват за задаване на инструкции към компилатора . Предпроцесорните директиви са изброени тук :
#define #error #include
#elif #if #line
#else #ifdef #pragma
#endif #ifndef #undef
Всяка е разгледана накратко в тази секция
#define
Директивата #define се използва да изпълни заместване със макрос на една част от текста със друга навсякъде във файла в който е използвана . Общата форма на директивата е :
#define име_на_макрос символна- последователност
Тук , всеки път когато име_на_макрос се срещне се замества със определената символна последователност . Забележете че няма точка и запетайка в този израз .Освен това когато започне символната поредица тя се прекъсва само от края на реда . Например ако искате да използвате стойност 1 за думата “TRUE ” и стойност 0 за “FALSE “ , трябва да декларирате тези два израза #define :
#define TRUE 1
#define FALSE 0
това ще предизвика компилатора да замести със 1 или 0 всеки път когато думите TRUE или FALSE се срещнат . Директивата #define има и друго свойство : макроса може да има аргументи . Макрос който приема аргументи действа почти като функция . Всъщност , този тип макрос е често определян като макрос подобен на функция . Всеки път когато макроса се срещне , аргументите свързани със него се заместват със действителните аргументи във програмата. Това е пример :
# include < iostream >
using namespace std ;
# define ABS ( a ) ( ( a ) < 0 ? - ( a ) : ( a ) )
int main ( )
{
cout << “ abs of -1 and 1 : “ << ABS (-1 ) << ‘ ‘
<< ABS (1) ;
return 0 ;
}
Когато тази програма се компилира а във макросната дефиниция ще се замести със стойностите - 1 и 1 .
Програмен съвет
Трябва да поставите във скоби макросите подобни на функция когато ги създавате . Ако не го направите , те може да не работят във всички ситуации . Например ограждането на а във предишния пример е необходимо за осигуряване на правилното заместване във всички случай . Ако ограждането бъде махнато израза :
ABS ( 10 – 20 )
ще бъде преобразуван във :
10 – 20 ? – 10 - 20 : 10 – 20
и се получава грешен резултат . Ако имате макрос подобен на функция който не се държи правилно проверете огражданията.
#error
Директивата #error предизвиква компилатора да спре компилацията когато я срещне . Тя се използва главно при дебъгване . Общата й форма е :
#error съобщение
Когато се срещне #error се показват съобщение и номера на реда .
#if , #ifdef , #ifndef , #else , #elif , и #endif
Предпроцесорните директиви #if , #ifdef , #ifndef , #else , #elif и #endif се използват за селективна компилация на различни части от програмата . Общата идея е че ако израза след #if , #ifdef , или #ifndef е true кода който е между един от предходните и #endif ще се компилира , иначе ще бъде прескочен . #endif се използва да маркира края на блока #if . #else може да се използва със всяко от тях за да добави алтернатива . Общата форма на #if e :
#if израз- от –константи
Ако израз- от – константи е true , кода който следва непосредствено ще бъде компилиран . Общата форма на #ifdef e:
#ifdef име_на_макрос
Ако име_на_макрос е било дефинирано в израз #define кода след израза ще се компилира . Общата форма на #ifndef e :
#ifndef име_на_макрос
Ако име_на_макрос е недефинирано в израз #define кода след израза ще се компилира . Например , тук е показано как тези предпроцесорни директиви работят заедно . Следващия код ще отпечати “Hi Ted “ и “Hi Jon “ но не и
”Hi George “ :
#define ted 10
// . . .
#ifdef ted
cout << “Hi Ted \n ” ;
#endif
cout << “Hi Jon “ \n “ ;
#if 10 < 9
cout << “ Hi George \n “ ;
#endif
Директивата #elif се използва да създаде израз if – else – if . Нейната обща форма е :
#elif израз – от – константи
Можете да вържете заедно серия от #elif за манипулиране на различни алтернативи . Можете също да използвате #if или #elif за определяне дали е било дефинирано име на макрос чрез използване на предпроцесорния оператор defined.
Той има тази обща форма :
#if defined име_на_макрос
поредица от изрази
#endif
Ако име_на_макрос е било дефинирано , поредицата от изрази ще се компилира . В противен случай ще бъде прескочена . Например следващия фрагмент компилира условния код понеже DEBUG е дефиниран :
#define DEBUG
// . . .
int i = 100 ;
// . . .
#if defined DEBUG
cout << “value of I is : “ << i << endl ;
#endif
Можете също да поставите пред defined оператора ! за да предизвика условна компилация когато макроса не е дефиниран .
#include
Директивата #include инструктира компилатора да прочете и компилира друг сорс файл . Тя има тези общи форми :
#include “име_на_файл “
#include < име_на_файл >
Сорс файла който ще бъде четен трябва да бъде затворен между двойни кавички или ъглови скоби . Например :
#include
ще инструктира компилатора да прочете и компилира хедъра за функциите на С за I/O . Ако име_на_файл е затворено в ъглови скоби , файла се търси по начин определен от създателя на компилатора . Често това означава претърсване на някакво специално множество директории за хедърни файлове . Ако файловото име е заградено във кавички файла се търси по друг определен от изпълнението начин . За повечето случай това означава претърсване на текущата работна директория . Ако файла не е открит търсенето се повтаря както ако името на файла е поставено във ъглови скоби . Вие трябва да проверите ръководството на компилатора за повече подробности за разликите между тях . #include изразите могат да бъдат вложени във други включвани файлове . Докато всички версии на С++ приемат тези версии на #include , стандартния С++ дефинира хедъри в нов стил които се използват да включат информация за стандартната С++ библиотека . Хедърите в нов стил не са имена на файлове (въпреки че могат да се съпоставят на имена на файлове ) За включване на хедър в нов стил използвайте тази обща форма :
#include < име_на_хедър >
Тук име_на_хедър ще бъде един от хедърите в нов стил описани във Глава 2 . Например за включване на информация за хедър за I/O системата използвайте :
#include < iostream >
Понеже хедърите в нов стил не са имена на файлове , те не трябва да имат разширение .h . Вижте вашата документация на компилатора за повече информация за включването на стандартните С++ хедъри във вашите С++ програми .
#line
Директивата #line се използва да промени съдържанието на __LINE__ и __FILE__ , които са предефинирани идентификатори .Общата форма на командата е :
#line номер “име_на_файл “
където номер е някакво положително цяло число и име_на_файл е някакъв валиден файлов идетификатор . Стойността на номер става номера на текущия ред от кода и име_на_файл става името на сорс файла . Името на файла не е задължително . #line е обикновенно използвана за дебъгване и специални приложения . Идетификатора __LINE__ е цяло число и __FILE__ е нулево – терминиран низ . Например следващия код установява текущия брояч на редове на 10 и файловото име на ” test “ :
#line 10 “ test “
#pragma
Директивата #pragma е зависеща от изпълнението директива която позволява различни инструкции да бъдат подадени на компилатора . Например компилатора може да има опция да поддържа трасиране на изпълнението на програмата . Трасиращата опция тогава ще трябва да бъде определена чрез израз #pragma . Проверете вашата документация на компилатора за детайли и опции .
#undef
Директивата #undef премахва дефинирано преди това име на макрос . Общата форма е :
#undef име_на_макрос
Например във следващия код :
#define LEN 100
#define WIDTH 100
char array [ LEN ] [ WIDTH ] ;
#undef LEN
#undef WIDTH
/* от тази точка и двете LEN и WIDTH са недефинирани */
и двете LEN и WIDTH са дефинирани докато не се срещнат изразите #undef
Предпроцесорните оператори # и ##
С/С++ доставя два предпроцесорни оператора : # и ## . Тези оператори се използват за употреба във #define макросите .Оператора # предизвиква аргумента който предхожда да бъде преобразуван във низ със кавички . Например разгледайте следната програма :
#include < iostream >
using namespace std ;
#define mkstr (s) # s
int main( )
{
cout << mkstr (I like C++ ) ;
return 0 ;
}
Предпроцесора преобразува реда
cout << mkstr ( I like C++ ) ;
във
cout << “ I like C++ “ ;
Оператора ## се използва да свърже два символа . Например във следващата програма :
#include < iostream >
using namespace std ;
#define concat ( a , b ) a ## b
int main ( )
{
int xy = 10 ;
cout << concat ( x , y ) ;
return 0 ;
}
Предпроцесора трансформира
cout << concat ( x , y ) ;
във
cout << xy ;
Ако тези оператори изглеждат странни за вас , запомнете че те не са нужни или използвани във повечето програми . Те съществуват главно да позволят някой специални случай да бъда манипулирани от предпроцесора .
Предефинирани имена на макроси
С/С++ определя пет вградени предефинирани имена на макроси . Те са :
__LINE__
__FILE__
__DATE__
__TIME__
__cplusplus
Макросите __FILE__ и __LINE__ са описани в разглеждането на #line по – рано във тази глава . Другите са представени тук . Макроса __DATE__ е низ във формата месец / ден / година , който е датата на преобразуването на сорс файла във обектен код . Часът на превеждането на сорс файла във обектен код се съдържа като низ във __TIME__ . Формата на низа е час : минута : секунда . Макроса __cplusplus е дефиниран когато компилирате С++ програма . Този макрос няма да бъде дефиниран от С компилатор . Макроса __STDC__ е дефиниран когато компилирате С програма и може да бъде дефиниран от С++ компилатор . И в двата случая проверете документацията на компилатора за подробности . Повечето С/С++ компилатори дефинират различни други вградени макроси които се отнасят за специфичната среда и изпълнение .
Коментари
С++ дефинира два стила за коментари . Първия е многоредов коментар . Той започва със /* и завършва със */ Всичко между коментарните символи се отхвърля от компилатора . Многоредовия коментар може да бъде разширен на няколко реда . Втория тип коментар е едноредовия коментар . Той започва със // и завършва в края на реда . Многоредовия коментар е единствения тип коментар поддържан от С . Обаче повечето С компилатори приемат едноредовите коментари макар и че не са стандартни .
Сподели с приятели: |