26.2. Макросларни аниқлаш ва жойлаштириш
Макрос - бу программа (код) бўлаги бўлиб, кўриниши ва ишлаши худди функциядек. Бироқ у функция эмас. Функциялар ва макрослар ўртасида бир нечта фарқлар мавжуд:
программа матнида учраган макрос ифодаси ўз аниқланиши (танаси билан) билан препроцессор ишлаш пайтида, яъни программа компиляциясидан олдин алмаштирилади. Шу сабабли макрос функ-цияни чақириш билан боғлиқ қўшимча вақт сарфини талаб қилмайди;
макрослардан фойдаланиш программанинг бошланғич коди (матнини) катталашувига олиб келади. Бунга қарама-қарши ҳолда функция коди ягона нусхада бўлади ва у программа кодини қисқа-ришига олиб келади. Лекин функцияни чақириш учун қўшимча ресурслар сарфланади;
компилятор макросдаги турлар мослигини текширмайди. Шу сабабли, макросга аргумент жўнатишда турларнинг мослиги ёки аргу-ментлар сонининг тўғри келиши ёки келмаслиги ҳақидаги хатолик хабарлари берилмайди;
макрос бошланғич кодга программа бўлагини қўйиш воситаси бўлганлиги ва бундай бўлаклар матннинг турли жой-ларига қўйиш мумкинлиги сабабли макрослар билан боғлиқ фиксирланган, ягона адреслар бўлмайди. Шу сабабли макросларда кўрсаткичлар эълон қилиш ёки макрос адресларини ишлатиш имконияти йўқ.
Макросларни аниқлаш учун #define директивасидан фойдаланилади. Функцияга ўхшаб макрослар ҳам параметрларга эга бўлиши мумкин. Мисол учун иккита сонни кўпайтмасини ҳисобловчи макрос қуйидагича аниқланади:
#include
#define KUPAYTMA(x,y)((x)+(y))
int main()
{
int a=2, b=3;
c=KUPAYTMA(a,b);
cout<return 0;
}
Мисолдан кўриниб турибдики, ташқи кўриниши бўйича мак-рослардан фойдаланиш функциялардан фойдаланишга ўхшаш. Шунинг учун уларни айрим ҳолларда уларга псевдофункциялар деб аташади. Макрослар аниқланишининг яна бир ўзига хос томони шундаки, С++ тилида уларнинг номларини катта ҳарфлар билан ёзишга келишилган.
Юқоридаги мисолнинг ўзига хос кўринишидан бири бу макрос параметрларини қавс ичида ёзилишидир. Акс ҳолда макрос аниқлани-шини (танасини) матнга қўйишда мазмунан хатолик юзага келиши мумкин. Масалан,
#define KVADRAT(x) x*x
Программа матнида ушбу макрос ишлатилган сатр мавжуд бўлcин:
int y=KVADRAT(2);
у ҳолда, макрос аниқланишини матнга қўйиш натижасида программа матнида юқоридаги сатр қуйидаги кўринишга келади:
int y=2*2;
Лекин, программада макросни ишлатиш
int y=KVADRAT(x+1);
кўринишида бўлса, макрос аниқланишини матнга қўйиш натижасида ушбу сатр
int y=x+1*x+1;
кўрсатмаси билан алмаштириладики, бу албатта кутилган алмаш-тириш эмас. Шу сабабли, макрос аниқланишида умумий қоида сифатида параметрларни қавсга олиш тавсия этилади:
#define KVADRAT(x)(x)*(x)
Агар макрос чақирилишида турга келтириш операторидан фойдаланган ҳолат бўлса, макрос танасини тўлиқлигича қавсга олиш талаб қилинади. Мисол учун программа матнида макросга мурожаат қуйидагича бўлсин:
double x=(double)KVADRAT(x+1);
Бу ҳолда макрос аниқланиши
#define KVADRAT(x)((x)*(x))
кўриниши тўғри ҳисобланади.
Макрос аниқланишида охирги эслатма сифатида шуни қайд этиш керакки, ортиқча пробеллар макросдан фойдаланишда хатолик-ларга олиб келиши мумкин. Масалан
#define CHOP_QILISH (x)cout<макрос аниқланишида макрос номи CHOP_QILISH ва параметрлар рўйхати (x) ўртасида ортиқча пробел қўйилган. Препроцессор бу мак-росни параметрсиз макрос деб қабул қилади, ҳамда “(x)cout<#define CHOP_QILISH(x)cout<Агар макрос аниқланиши битта сатрга сиғмаса, шу сатр охирига ‘\’ белгисини қўйиш орқали кейинги сатрда давом эттириш мумкин:
#define BURCHAK3(a,b,c)(unsigned int)a+(unsigned int)b\
>(unsigned int)c &&(unsigned int)a+(unsigned int)с>\ (unsigned int)b &&(unsigned int)b+(unsigned int)с>\ (unsigned int)a
Макрос аниқланишида бошқа макрослар иштирок этиши мумкин. Қуйидаги мисолда ичма-ич жойлашган макрос аниқланиши кўрсатилган.
#define PI 3.14159
#define KVADRAT(x) ((x)*(x))
#define AYLANA_YUZI(r)(PI* KVADRAT(r))
Фойдаланишга зарурати қолмаган макросни программа матнининг ихтиёрий жойида #undef директиваси билан бекор қилиш мумкин, яъни шу сатрдан кейин макрос препроцессор учун ноаниқ ҳисобланади. Қуйида айлана юзасини ҳисоблайдиган программа матни келтирилган.
#include
#define PI 3.14159
#define KVADRAT(x) ((x)*(x))
#define AYLANA_YUZI(r)(PI* KVADRAT(r))
int main()
{
double r1=5,r2=10;
double c1,c2;
c1=AYLANA_YUZI(r1);
#undef AYLANA_YUZI
c2=AYLANA_YUZI(r2);
cout<cout<return 0;
}
Программа компиляциясида “c1=AYLANA_YUZI(r1);” сатр нормал қайти ишланган ҳолда “c2=AYLANA_YUZI(r2);” сатри учун AYLANA_YUZI функцияси аниқланмаганлиги ҳақида хатолик хабари чоп этилади.
Do'stlaringiz bilan baham: |