Si të konfiguroni telefonat inteligjentë dhe PC. Portali informativ
  • në shtëpi
  • Programet
  • Qëllimi i direktivës së përfshirjes së paraprocesorit. C direktivat e paraprocesorit

Qëllimi i direktivës së përfshirjes së paraprocesorit. C direktivat e paraprocesorit

Pothuajse të gjitha programet C++ përdorin komanda të veçanta përpilues të quajtur direktiva. Në përgjithësi, një direktivë është një udhëzim për përpiluesin C++ për të kryer një ose një veprim tjetër në kohën e përpilimit të programit. Ekziston një grup i përcaktuar rreptësisht i direktivave të mundshme, i cili përfshin përkufizimet e mëposhtme:

#përcakto, #elif, #tjetër, #endif, #nëse, #ifdef, #ifndef, #përfshi, #undef.

Direktiva #define përdoret për të përcaktuar konstante, fjalë kyçe, operatorë dhe shprehje të përdorura në një program. Sintaksa e përgjithshme për këtë direktivë është si më poshtë:

Duhet të theksohet se simboli ';' nuk vendoset pas direktivave. Le të japim shembuj të opsioneve për përdorimin e direktivës #define.

Listimi 1.2. Shembuj të përdorimit të direktivës #define.

#përfshi
#përcaktoni DY 2
#define FOUR DY * DY
#define PX printf("X është e barabartë me %d.\n", x)
#define FMT "X është e barabartë me %d.\n"
#define SQUARE(X) X*X
int main()
{
int x = DY;
PX;
x=KATËR;
printf(FMT, x);
x = KATROR (3);
PX;

kthimi 0;
}

Pas ekzekutimit të këtij programi, në ekranin e monitorit do të shfaqen tre rreshta:

X është 2.
X është 4.
X është 9.

Direktiva #undef tejkalon përkufizimin e paraqitur më herët nga direktiva #define. Supozoni se në një moment në program ju duhet të pacaktoni konstanten FOUR. Kjo arrihet me komandën e mëposhtme:

Një tipar interesant i kësaj direktive është aftësia për të ripërcaktuar vlerën e një konstante të futur më parë. Në të vërtetë, ripërdorimi i direktivës #define për konstanten FOUR të prezantuar më parë është i pamundur, sepse kjo do të rezultojë në një mesazh gabimi në kohën e kompilimit të programit. Por nëse e definoni konstanten FOUR me direktivën #undef, mund të ripërdorni direktivën #define për konstanten FOUR.

Për të mundësuar kryerjen e kompilimit me kusht, përdoren një grup direktivash #if, #ifdef, #ifndef, #elif, #else dhe #endif. Programi më poshtë lidh bibliotekat në varësi të konstantave të vendosura.

#nëse përcaktohet (GRAPH)
#elif përcaktuar (TEXT)
#tjetër
#përfundim

Ky program funksionon si më poshtë. Nëse një konstante me emrin GRAPH ishte vendosur më parë përmes direktivës #define, atëherë biblioteka grafike do të përfshihet duke përdorur direktivën #include. Nëse identifikuesi GRAPH nuk është i përcaktuar, por është përcaktuar TEXT, atëherë do të përdoret biblioteka e tekstit I/O. Përndryshe, në mungesë të ndonjë definicioni, përfshihet biblioteka I/O. Në vend të frazës #if defined, shpesh përdoren shkurtesat #ifdef dhe #ifndef, dhe programi i mësipërm mund të rishkruhet si:

#ifdef GRAPH
#include //lidhja e bibliotekës grafike
#ifdef TEKST
#include //include text library
#tjetër
#include //lidhja e bibliotekës I/O
#përfundim

Dallimi midis direktivës #if dhe direktivave #ifdef dhe #ifndef është aftësia për të kontrolluar për kushte më të ndryshme, dhe jo vetëm nëse ekzistojnë ose jo disa konstante. Për shembull, duke përdorur direktivën #if, mund të kryeni kontrollin e mëposhtëm:

#nëse SIZE == 1
#përfshi // lidhjen e bibliotekës matematikore
#elif SIZE > 1
#include // lidhjen e bibliotekës së përpunimit të grupit
#përfundim

Në shembullin e mësipërm, përfshihet ose një bibliotekë matematike ose një bibliotekë e përpunimit të vargjeve, në varësi të vlerës së konstantës SIZE.

Këto direktiva përdoren ndonjëherë për të theksuar blloqet e nevojshme të programit që dëshironi të përdorni në një zbatim të caktuar softueri. Shembulli i mëposhtëm tregon se si funksionon një kod i tillë.

Listimi 1.3. Një shembull i përpilimit të blloqeve individuale të programit.

#përfshi
#përcaktoni KATRIN
int main()
{
int s = 0;
gjatësia int = 10;
gjerësia int = 5;

SHESHI #ifdef
s=gjatësia*gjerësia;
#tjetër
s=2*(gjatesi+gjeresi);
#përfundim

kthimi 0;
}

Në këtë shembull, llogaritet ose sipërfaqja e një drejtkëndëshi ose perimetri i tij, në varësi të faktit nëse vlera SQUARE është përcaktuar apo jo. Si parazgjedhje, programi llogarit sipërfaqen e një drejtkëndëshi, por nëse hiqni vijën #define SQUARE, programi do të llogarisë perimetrin e tij.

Direktiva #include e përdorur në shembujt e mësipërm ju lejon të shtoni programe të shkruara më parë dhe t'i ruani ato si skedarë në program. Për shembull, linja

#include < stdio.h >

i thotë paraprocesorit të shtojë përmbajtjen e skedarit stdio.h në vend të rreshtit të dhënë. Kjo jep fleksibilitet më të madh, lehtësi programimi dhe dukshmëri të tekstit të krijuar të programit. Ekzistojnë dy variante të direktivës #include:

#include < stdio.h > - emri i skedarit në kllapa këndore

#include "mylib.h" - emri i skedarit në thonjëza

Kllapat e këndit i tregojnë paraprocesorit të kërkojë një skedar (në këtë rast, stdio.h) në një ose më shumë nga drejtoritë standarde të sistemit. Thomat tregojnë se paraprocesori duhet së pari të kërkojë skedarin në drejtorinë aktuale, d.m.th. ku ndodhet skedari i programit që po krijohet, dhe vetëm atëherë - shikoni në drejtoritë standarde.

Në këtë artikull, ne do të vazhdojmë të mësojmë artin e programimit C++. Në këtë pikë të tutorialit, është koha për t'u njohur me gjëra të tilla si direktivat e paraprocesorit. Duke parë përpara, do të them se në mësimet e mëparshme ne kemi përdorur tashmë direktivën #përfshi, i cili përdoret për të përfshirë skedarët e kokës.

Së pari, le të përcaktojmë se çfarë është një paraprocesor. Kompilimi i çdo programi bëhet në disa faza, ku një nga të parat është përpunimi nga paraprocesori. Me fjalë të thjeshta, një paraprocesor është një program që lexon kodin burimor të programit dhe e ndryshon atë në bazë të direktivave. Skematikisht, i gjithë procesi i montimit të programit mund të përfaqësohet si më poshtë.

Siç mund ta shihni, para përpilimit, kodi burimor i programit përpunohet nga paraprocesori, le të hedhim një vështrim më të afërt në udhëzimet e tij.

Le të fillojmë me direktivën #include, e cila zëvendësohet nga paraprocesori me përmbajtjen e skedarit pas tij. Një shembull i përdorimit të #include:

#përfshi

#include "header2.h"

Nëse emri i skedarit është i mbyllur në kllapa këndore, atëherë paraprocesori e kërkon skedarin në një vend të paracaktuar. Përdorimi i kllapave të dyfishta nënkupton përfshirjen e një skedari nga e njëjta direktori me kodin burimor të programit të përpiluar. Vlen gjithashtu të theksohet se skedarët e përfshirë mund të përmbajnë gjithashtu direktiva të paraprocesorit, në veçanti direktivën #include, kështu që mund të ketë probleme me përfshirjen e të njëjtit skedar disa herë. Për të shmangur këtë lloj konfuzioni, u prezantuan direktiva të kushtëzuara, le të shohim një shembull të përdorimit të tyre:

#ifndef CCUMBLER_H

#define CUCUMBLER_H

/* Përmbajtja e skedarit cucumbler.h */

Direktiva #ifndef kontrollon nëse konstanta CUCUMBLER_H është përcaktuar më parë, dhe nëse përgjigja është negative, atëherë kjo konstante përcaktohet dhe kodi tjetër që pason përpara direktivës #endif. Siç mund ta merrni me mend, direktiva #define përcakton konstanten CUCUMBLER_H. Në këtë rast, një pjesë e tillë e kodit ndihmon në shmangien e përfshirjes së shumëfishtë të të njëjtit kod, pasi pas përfshirjes së parë, konstanta CUCUMBLER_H inicializohet dhe kontrollet pasuese #ifndef CUCUMBLER_H do të kthehen FALSE.

Direktiva #define përdoret gjithashtu gjerësisht kur korrigjoni një program.

#përfshi

#përfshi

#përfshi

duke përdorur hapësirën e emrave std;

cout<< "Начало функции main()\n";

vektoriale grup_teksti;

ndërsa (cin >> tekst)

cout<< "Прочитан текст: " << text << "\n";

teksti_array.push_mbrapa(tekst);

Nëse konstanta IN_DEBUG nuk është vendosur, atëherë paraprocesori do të gjenerojë burimin e mëposhtëm:

#përfshi

#përfshi

#përfshi

duke përdorur hapësirën e emrave std;

vektoriale grup_teksti;

ndërsa (cin >> tekst)

teksti_array.push_mbrapa(tekst);

Por nëse përcaktoni IN_DEBUG, atëherë teksti i programit do të ndryshojë në mënyrë dramatike

#përfshi

#përfshi

#përfshi

duke përdorur hapësirën e emrave std;

cout<< "Начало функции main()\n";

vektoriale grup_teksti;

ndërsa (cin >> tekst)

cout<< "Прочитан текст: " << text << "\n";

teksti_array.push_mbrapa(tekst);

Mund ta vendosni konstanten e paraprocesorit direkt nga tastiera. Për shembull, përpiluesi g++ përdor formatin e mëposhtëm

#përfshi

Direktiva #include fut kodin nga skedari i specifikuar në skedarin aktual, domethënë, duke përfshirë thjesht një skedar tjetër, ne mund të përdorim funksionet, klasat dhe variablat e tij. Skedarët e kokës zakonisht gjenden ose në drejtorinë aktuale ose në drejtorinë standarde të sistemit.

Skedarët e kokës përfshihen në kohën e përpilimit, ose si skedar që është pjesë e projektit tuaj. Kjo veçori varet nga zbatimi specifik i përpiluesit tuaj, kështu që për më shumë detaje, gërmoni në cilësimet e përpiluesit tuaj.

Nëse skedari i përfshirjes nuk gjendet, procesi i përpilimit dështon.

#përcaktoni direktivën

Direktiva #define merr dy forma:

  • përcaktimi i konstanteve;
  • përkufizimi i makrove.
Përkufizimi i konstanteve
#define nameToken vlerë

Kur përdorni emrin e konstantës - nameToken , ai do të zëvendësohet nga vlera e vlerës , domethënë, përafërsisht, kjo është e njëjta ndryshore vlera e së cilës nuk mund të ndryshohet. Le të shohim një shembull të përdorimit të një konstante:

#përfshi #define TEXT "Mars" // duke përcaktuar një int main() konstante ( std::cout<< TEXT; return 0; }

Siç mund ta shihni, për të hyrë në vlerën e një konstante, ne thjesht përdorim emrin e saj.

Përcaktimi i makrove të parametrizuara

#define shprehje nameMacros(arg1, arg2, ...).

Për shembull, le të përcaktojmë një makro që do të kthejë maksimumin e dy vlerave.

#define MAX(num1, num2) ((num1) > (num2) ? (num1) : (num2))

Kujdes, për të përcaktuar një makro me shumë rreshta, çdo rresht duhet të përfundojë me një karakter, i cili informon paraprocesorin se makroja nuk ka përfunduar ende.

Direktiva #undef

Direktiva #undef anulon një makro konstante ose paraprocesore të përcaktuar më parë me direktivën #define.

#undef nameToken

Le të shohim një shembull të përdorimit të direktivës #undef:

#define E 2.71828 // makro e përcaktuar më parë int sumE = E + E; // thirrje për makro #undef E // tani E nuk është një makro

Në mënyrë tipike, direktiva #undef përdoret për të hequr një konstante ose makro të përcaktuar më parë nga një zonë e vogël e programit. Kjo bëhet në mënyrë që për të gjithë programin, makroja ose konstanta të mbetet, dhe për disa zona, e njëjta makro ose konstante mund të ripërcaktohet. Do të ishte e pasigurt të ripërcaktohej një konstante gjatë gjithë programit, por në një zonë të shkurtër, është relativisht e sigurt. Direktiva #undef është e vetmja mënyrë për të krijuar këtë shtrirje, sepse shtrirja e makros ose konstanteve është nga #define në #undef.

#nëse direktivë

#if vlera // kodi do të ekzekutohet nëse vlera është e vërtetë #elsif vlera1 // ky kod do të ekzekutohet nëse vlera1 është e vërtetë #else // kodi do të ekzekutohet ndryshe #endif

Direktiva #if kontrollon nëse vlera është e vërtetë dhe, nëse po, ekzekuton kodin që vjen përpara direktivës mbyllëse #endif. Përndryshe, kodi brenda #if nuk do të përpilohet, ai do të hiqet nga përpiluesi, por kjo nuk ndikon në kodin origjinal në burim.

Vini re se #if mund të ketë direktiva të mbivendosura #elsif dhe #else. Më poshtë është një shembull kodi për komentimin e blloqeve të kodit duke përdorur konstruktin e mëposhtëm:

#if 0 // kodi për tu komentuar #endif

Nëse keni blloqe kodi në programin tuaj që përmbajnë komente me shumë rreshta dhe duhet të mbështillni të gjithë bllokun e kodit në një koment, asgjë nuk do të funksionojë nëse përdorni /* koment me shumë rreshta */ . Një gjë tjetër është ndërtimi i direktivave #if #endif.

Direktiva #ifdef

#ifdef nameToken // kodi që do të ekzekutohet nëse definohet nameToken #else // kodi që do të ekzekutohet nëse nameToken nuk është përcaktuar #endif

Direktiva #ifdef kontrollon nëse një konstante makro ose simbolike është përcaktuar më parë si #define. Nëse - po, përpiluesi përfshin në program kodin që është midis direktivave #ifdef dhe #else, nëse nameToken nuk ishte përcaktuar më parë, atëherë kodi midis #else dhe #endif ekzekutohet, ose, nëse nuk ka #else direktiva, përpiluesi hidhet menjëherë në # endif. Për shembull, makro __cpp përcaktohet në C++ por jo në C. Ju mund ta përdorni këtë fakt për të përzier kodin C dhe C++ duke përdorur direktivën #ifdef:

#ifdef __cpp // Kodi C++ #else // Kodi C #endif

Direktiva #ifndef

#ifndef nameToken // kodi që do të ekzekutohet nëse nameToken nuk është përcaktuar #else // kodi që do të ekzekutohet nëse definohet nameToken #endif

Direktiva #ifndef kontrollon nëse një konstante makro ose simbolike është përcaktuar më parë si #define. Nëse - po, përpiluesi përfshin kodin midis direktivave #else dhe #endif në program, nëse nameToken nuk ishte përcaktuar më parë, atëherë kodi midis #ifndef dhe #else ekzekutohet, ose nëse nuk ka direktivë #else, përpiluesi hidhet menjëherë në # endif. Direktiva #ifndef mund të përdoret për të përfshirë skedarët e kokës. nëse nuk janë të lidhur, për ta bërë këtë, përdorni një konstante simbolike si tregues të funksionalitetit të lidhur me projektin.

Për shembull, në skedarin e kokës ekziston një ndërfaqe e klasës që duhet të përfshihet në projekt nëse kjo klasë nuk është përfshirë më parë.

#ifndef PRODUCT_H #define PRODUCT_H class Product ( // kodi i klasës... ); #endif PRODUCT_H

Në këtë rast, përdoret konstanta simbolike boshe PRODUCT_H, e cila mund të përcaktohet vetëm në program së bashku me klasën Product. Prandaj, nëse konstatojmë se konstantja PRODUCT_H është tashmë e përcaktuar, atëherë klasa është tashmë e përcaktuar, dhe më pas shmangim ripërcaktimin e klasës, gjë që mund të çojë në një gabim ripërcaktimi.

Direktiva #gabim

#error "Ky kod nuk duhet të përpilohet"

Direktiva #error ju lejon të shfaqni një mesazh në listën e gabimeve të përpilimit nëse ndodh një gabim përkatës. Kjo direktivë është më e dobishme në kombinim me direktivat #if , #elsif , #else për të kontrolluar përpilimin nëse një kusht nuk është i vërtetë. Për shembull:

#ifndef __unix__ // __unix__ mbështetet përgjithësisht në sistemet Unix #gabim "Mbështetet vetëm në Unix" #endif

Makroja e paraprocesorit __FILE__

Makroja e paraprocesorit __FILE__ zgjerohet në shtegun e plotë drejt skedarit aktual (burimi). __FILE__ është i dobishëm për krijimin e një skedari log, gjenerimin e mesazheve të gabimit të destinuara për programuesit dhe korrigjimin e kodit.

gabim int (const char* adrFile, const std::string& erMessage) ( cerr<< "[" << adrFile << "]" << arMessage << endl; } #define LOG(erMessage) error(__FILE__, arMessage) // макрос LOG может быть использован для получения сообщений об ошибках, которые выводятся на стандартный поток ошибок

Makroja __FILE__ përdoret shpesh në lidhje me makronë __LINE__, e cila siguron numrin aktual të linjës.

Makro paraprocesor __LINE__

Makroja __LINE__ zgjerohet në numrin aktual të linjës në skedarin burimor, si një vlerë e plotë. __LINE__ është i dobishëm për krijimin e një skedari regjistri ose për gjenerimin e mesazheve të gabimit me numra rreshtash të destinuar për programuesit gjatë korrigjimit të kodit.

gabim int (int nLine, const std::string& erMessage) ( cerr<< "[" << nLine << "]" << erMessage << endl; } #define LOG(erMessage) error(__LINE__, erMessage) // макрос LOG может быть использован для получения сообщений об ошибках, с указанием номеров строк, которые выводятся на стандартный поток ошибок

Makroja __LINE__ përdoret shpesh në lidhje me makronë __FILE__, e cila tregon adresën e skedarit aktual burimor.

Makroja e paraprocesorit __DATE__

Makroja __DATE__ zgjerohet në datën aktuale (koha e përpilimit) si [ddmm vvvvv] (p.sh. "Dec 7 2012") si varg. __DATE__ mund të përdoret për të dhënë informacione për kohën e përpilimit.

Cout<< __DATE__ << endl;

Mund të përdorni gjithashtu makro __TIME__ për të marrë kohën aktuale të përpilimit.

Makro paraprocesor __TIME__

Makroja __TIME__ zgjerohet në kohën aktuale (koha e përpilimit) në formatin hh:mm:cc në formatin 24-orësh (p.sh. "22:29:12"). Makroja __TIME__ mund të përdoret për të dhënë informacion në lidhje me kohën në një pikë të caktuar të përpilimit.

Cout<< __TIME__ << endl;

Makroja e paraprocesorit __TIMESTAMP__

Makroja __TIMESTAMP__ zgjerohet në kohën aktuale (koha e përpilimit) në formatin Ddd Mmm Data hh::mm::ss yyyy, ora në formatin 24-orësh:

  • Ddd është e shkurtër për ditën e javës.
  • mmm është shkurtuar muaji,
  • Data - dita aktuale e muajit (1-31),
  • yyyy është katër shifrat e vitit.

Për shembull, "Premte Dhjetor 7 00:42:53 2012" . Makro __TIMESTAMP__ mund të përdoret për të marrë informacion në lidhje me datën dhe kohën e përpilimit.

Cout<< __TIMESTAMP__ << endl;

Mund të përdorni gjithashtu makron __TIME__ për të marrë kohën aktuale të përpilimit dhe makron __DATE__ për të marrë datën.

Direktiva #pragma

Zgjerimi specifik i përpiluesit #pragma

Direktiva #pragma përdoret për të hyrë në shtesa specifike të përpiluesit. Ndarja e direktivës #pragma me tokenin Once i thotë përpiluesit të përfshijë skedarin e kokës vetëm një herë, pavarësisht sa herë është importuar:

#pragma Once // skedari i kokës

Në këtë shembull, direktiva #pragma Once parandalon përfshirjen e skedarit në projekt më shumë se një herë, pra parandalon ripërcaktimin.

Direktiva #pragma mund të përdoret gjithashtu për qëllime të tjera, për shembull #pragma përdoret zakonisht për të çaktivizuar paralajmërimet. Për shembull, në MVS:

paralajmërim #pragma (çaktivizoj: 4018)

Direktiva #pragma në këtë shembull përdoret për të çaktivizuar paralajmërimet 4018. Për më shumë informacion mbi përdorimin e direktivës #pragma, shihni dokumentacionin e përpiluesit tuaj.

Operatori makro #

#

Operatori # një shenjë teksti në një varg të cituar. Le të shohim një shembull:

#përfshi duke përdorur hapësirën e emrave std; #define mesazh(et) cout<< "Сообщение: " #s << endl; int main() { message("GunGame"); return 0; }

Vargjet janë të lidhura dhe makroja e mesazhit zgjerohet në cout<< "Сообщение: GunGamen"; . Обратите внимание на то, что операция # должна использоваться совместно с аргументами, так как # ссылается на аргумент.

Operatori makro ##

Operatori ## merr dy shenja të veçanta dhe i ngjit ato së bashku për të formuar një makro. Rezultati mund të jetë një emër variabli, një emër klase ose ndonjë identifikues tjetër. Për shembull:

#define type ch##ar type a; // ndryshorja a është lloji i të dhënave char, sepse ch dhe ar janë ngjitur në char

Konsideroni një shembull tjetër të përdorimit të operatorit ##, në të cilin kombinojmë dy shenja:

#define TOKENCONCAT(x,y) x##y

Kur një program e thërret këtë makro, të dy shenjat kombinohen në një. Operacioni ## duhet të ketë dy operandë.

P.S.: Çdo program serioz duhet të ketë bazën e tij të të dhënave, zakonisht DBMS-të e mëposhtme përdoren për të menaxhuar bazën e të dhënave: MySQL, MsSQL, PostgreeSQL, Oracle, etj. Kur instaloni serverin sql, forumi cyberforum.ru do të jetë një ndihmës i domosdoshëm për ju. Bëni pyetjet tuaja në këtë forum, patjetër që do të ndihmoheni në zgjidhjen e problemit tuaj.

paraprocesor . Qëllimi i një paraprocesori është të përpunojë kodin burimor të një programi përpara se ta përpilojë atë. Parapërpunimi përfshin disa faza që kryhen në mënyrë sekuenciale. Një zbatim i veçantë mund të kombinojë disa faza, por rezultati duhet të jetë i njëjtë sikur të ishin kryer në rendin e mëposhtëm:
  1. Të gjitha emërtimet e varura nga sistemi rikodohen në kode standarde.
  2. Çdo çift karakteresh "\" dhe "fundi i rreshtit" së bashku me hapësirat ndërmjet tyre hiqen dhe kështu rreshti tjetër i tekstit burim i bashkëngjitet rreshtit në të cilin ndodhej ky çift karakteresh.
  3. Direktivat dhe shenjat e paraprocesorit njihen në tekst dhe çdo koment zëvendësohet me një karakter të vetëm të hapësirës së bardhë.
  4. Ekzekutohen direktivat e paraprocesorëve dhe bëhen zëvendësimet makro.
  5. Sekuencat e arratisjes në karaktere konstantet dhe vargjet e karaktereve zëvendësohen me ekuivalentët e tyre.
  6. Vargjet e karaktereve të njëpasnjëshme janë të lidhura, d.m.th. të kombinuara në një varg.
  7. Çdo shenjë paraprocesori konvertohet në tekst C.

Le të shpjegojmë se çfarë nënkuptohet me shenjat paraprocesore ose shenjat paraprocesore. Këto përfshijnë konstantet e karaktereve, përfshijnë emrat e skedarëve, identifikuesit, shenjat e funksionimit, numrat e paraprocesorit, shenjat e pikësimit, konstantet e vargjeve dhe çdo karakter pa hapësirë ​​të bardhë.

Faza e përpunimit të direktivave të paraprocesorëve. Kur ekzekutohet, veprimet e mëposhtme janë të mundshme:

  • zëvendësimi i identifikuesve me sekuenca karakteresh të përgatitura paraprakisht;
  • përfshirja në program e teksteve nga skedarët e specifikuar;
  • përjashtimi nga programi i pjesëve individuale të tekstit të tij, përpilimi i kushtëzuar;
  • zëvendësimi makro, domethënë zëvendësimi i emërtimit me tekst të parametrizuar të krijuar nga paraprocesori, duke marrë parasysh argumentet specifike.

Konstantet simbolike: #define

Nëse # përdoret si karakteri i parë në një linjë programi, atëherë ajo rresht është linja e komandës paraprocesor (makroprocesor). Linja e komandës paraprocesori përfundon me një karakter të linjës së re. Nëse menjëherë paraprin fundin e vargut me një karakter " \ ", atëherë linja e komandës do të vazhdojë në rreshtin tjetër të programit.

Direktiva #define, si të gjitha direktivat e paraprocesorit, fillon me një karakter # në pozicionin më të majtë. Mund të shfaqet kudo në skedarin burimor dhe përkufizimi i dhënë është i vlefshëm nga vendi ku shfaqet deri në fund të skedarit. Ne e përdorim këtë direktivë gjerësisht për të përcaktuar konstante simbolike në programet tona mostër, megjithatë, ai ka një aplikim më të gjerë, të cilin do ta tregojmë në vijim.

Zëvendësimi i identifikuesve

#define varg identifikues

Zëvendëson çdo dukuri të identifikuesit ABC në tekstin e programit me 100:

#undef identifikues

Rikthen përkufizimin e mëparshëm për identifikuesin ABC.

/* Shembuj të thjeshtë të direktivës së paraprocesorit */ #define TWO 2 /* mund të përdoren komente */ #define MSG "Text 1.\ Teksti 1 vazhdon" /* Backslash vazhdon përkufizimin në rreshtin tjetër */ #define FOUR TWO*TWO # define PX printf("X është %d.\n", x) #define FMT "X është %d.\n" int main() ( int x = TWO; PX; x = FOUR; printf(FMT,x ) ; printf("%s\n",MSG); printf("TWO: MSG\n"); kthe dy;)

Si rezultat i shembullit tonë, ne do të kemi.

Përditësimi i fundit: 22.05.2017

Paraprocesori është një komponent i kërkuar i përpiluesit C. Paraprocesori përpunon kodin burimor të programit përpara se ai të kompilohet. Rezultati i paraprocesorit është teksti i plotë i programit, i cili transferohet në kompilim në një skedar të ekzekutueshëm.

Për të kontrolluar paraprocesorin, përdoren direktivat, secila prej të cilave fillon me shenjën e paundit # dhe ndodhet në një linjë të veçantë. Paraprocesori shikon tekstin e programit, i gjen këto direktiva dhe i përpunon siç duhet.

Ne mund të përdorim udhëzimet e mëposhtme:

    #define: përcakton një identifikues makro ose paraprocesor

    #undef: nuk përcakton një makro ose identifikues

    #ifdef: kontrollon nëse identifikuesi është i përcaktuar

    #ifndef: kontrollon për identifikues të papërcaktuar

    #include : përfshin tekst nga skedari

    #if : teston shprehjen e kushtit (si një if i kushtëzuar)

    #else : specifikon një kusht alternativ për #if

    #endif : fundi i direktivës #if kushtëzuar

    #elif : specifikon një kusht alternativ për #if

    #line : ndryshon numrin e rreshtit tjetër më poshtë

    #error : formon tekstin e mesazhit të gabimit të përkthimit

    #pragma : përcakton veprimet që varen nga zbatimi i veçantë i përpiluesit

    # : direktiva boshe, nuk bën asgjë

Konsideroni kryesoret e këtyre direktivave.

Direktiva #përfshi. Përfshirë skedarët

Direktiva #include është përdorur tashmë më parë. Kjo direktivë përfshin skedarët në tekstin burimor. Ai ka përdorimet e mëposhtme:

#përfshi<имя_файла>// emri i skedarit në kllapa këndore #include "filename" // filename në thonjëza

Për shembull, nëse duhet të përdorim konsolën I/O në një aplikacion duke përdorur funksionet printf() ose scanf(), atëherë duhet të përfshijmë skedarin "stdio.h", i cili përmban përkufizimin e këtyre funksioneve:

#përfshi

Kur kjo direktivë ekzekutohet, paraprocesori fut tekstin e skedarit stdio.h. Ky skedar quhet gjithashtu skedar me kokë. Skedarët e kokës përmbajnë prototipe funksioni, përkufizime dhe deklarata të llojeve dhe konstanteve dhe kanë shtrirjen .h.

Kërkimi i skedarëve kryhet në drejtoritë standarde të sistemit. Në përgjithësi, ekziston një grup standard i skedarëve të kokës së integruar, i cili përcaktohet nga standardi i gjuhës dhe që mund t'i përdorim:

    pohoj.h : përgjegjës për diagnostifikimin e programit

    kompleks.h : për trajtimin e numrave kompleks

    ctype.h : përgjegjës për konvertimin dhe vërtetimin e karaktereve

    errno.h : përgjegjës për kontrollin e gabimeve

    fenv.h: për të hyrë në mjedisin që trajton operacionet me pikë lundruese

    float.h : përgjegjës për punën me numrat me pikë lundruese

    inttypes.h : për trajtimin e numrave të plotë të mëdhenj

    iso646.h : përmban një numër përkufizimesh që zgjerojnë një numër operacionesh logjike

    limits.h : përmban vlera kufitare të llojeve të numrave të plotë

    locale.h : përgjegjës për të punuar me kulturën lokale

    matematikë.h : për punën me shprehjet matematikore

    setjmp.h : përcakton mundësitë e kërcimeve jo lokale

    sinjal.h: për trajtimin e përjashtimeve

    stdalign.h: për shtrirjen e tipit

    stdarg.h: ofron mbështetje për numrin e ndryshueshëm të parametrave

    stdatomic.h : për të kryer operacione atomike në të dhëna të përbashkëta midis thread-eve

    stdbool.h: për të punuar me llojin _Bool

    stddef.h : përmban një numër përkufizimesh ndihmëse

    stdint.h : për të punuar me numra të plotë

    stdio.h : për të punuar me objektet I/O

    stdlib.h : përmban përkufizime dhe prototipe të funksioneve publike

    stdnoreturn.h : përmban makro noretturn

    varg.h : për të punuar me vargje

    tgmath.h : përfshin math.h dhe kompleks.h plus shton aftësi shtesë matematikore

    fijet.h : për të punuar me fije

    koha.h : për të punuar me datat dhe oraret

    uchar.h: për të punuar me karaktere Unicode

    wchar.h : për të punuar me personazhe

    wctype.h : përmban veçori shtesë për të punuar me karaktere

Sidoqoftë, vlen të përmendet se në mjedise të ndryshme, skedarë shtesë të integruar të kokës mund të shtohen në këtë grup për qëllime të caktuara, për shembull, për të punuar me grafikë.

Përveç skedarëve standardë të kokës, ne mund të përfshijmë skedarët tanë. Për shembull, në të njëjtën dosje me skedarin kryesor të programit, le të përcaktojmë një skedar tjetër, të cilin do ta quajmë main.c. Le të përcaktojmë kodin e mëposhtëm në të:

numri int = 5;

Ai përcakton vetëm një variabël. Tani le të përfshijmë këtë skedar në program:

#përfshi #include "main.c" int main(void) ( printf("%d", numër); // 5 return 0; )

Kur lidhni skedarët tuaj, emri i tyre tregohet në thonjëza. Dhe përkundër faktit se variabli numër nuk është i përcaktuar në program, ai do të merret nga skedari main.c i përfshirë. Por përsëri, vërej se është e rëndësishme që në këtë rast skedari main.c të jetë i vendosur në të njëjtën dosje me skedarët kryesorë të programit.

Në të njëjtën kohë, kjo metodë funksionon mirë në GCC. Por për mjedise të ndryshme programimi, mënyra e lidhjes së skedarëve mund të ndryshojë. Për shembull, në Visual Studio do të kemi një gabim. Dhe një qasje më e saktë do të ishte përcaktimi i deklarimit të një objekti (ndryshore / konstante) ose funksioni në një skedar shtesë të kokës dhe vendosja e përkufizimit të objektit ose funksionit në një skedar standard me një shtrirje .c.

Për shembull, në skedarin tonë main.c ekziston tashmë një përkufizim i ndryshores së numrit. Tani le të shtojmë një skedar të ri main.h në të njëjtën dosje - një skedar me të njëjtin emër, por me një shtrirje të ndryshme. Dhe përcaktoni kodin e mëposhtëm në main.h:

numri int i jashtëm;

Fjala kyçe e jashtme tregon se objekti i dhënë është i jashtëm. Dhe në këtë rast, ne mund ta përfshijmë atë në skedarin e kodit burimor:

#përfshi #include "main.h" // deklarimin ose përshkrimin e objektit #include "main.c" // përkufizimin e objektit int main(void) (printf("%d", numër); kthej 0; )

Ky shembull do të funksionojë gjithashtu në GCC, megjithatë, siç u diskutua më lart, përfshirja e skedarit main.h për GCC është opsionale.

Nëse zhvillimi kryhet në Visual Studio, atëherë përkufizimi i objektit nuk ka nevojë të përfshijë skedarin burimor:

#përfshi #include "main.h" // deklarimin ose përshkrimin e objektit int main(void) ( printf("%d", numër); kthej 0; )

Pavarësisht nga fakti se skedari main.c nuk përfshihet në mënyrë eksplicite këtu, kur përkthen Visual Studio përmes skedarit të kokës main.h, ai do të jetë në gjendje të përfshijë skedarin main.c të vendosur në të njëjtën dosje.

Artikujt kryesorë të lidhur