După cum sugerează și numele, preprocesoarele sunt programe care procesează codul nostru sursă înainte de compilare. Există o serie de pași implicați între scrierea unui program și execuția unui program în C / C++. Să aruncăm o privire asupra acestor etape înainte de a începe efectiv să învățăm despre Preprocesoare.
Puteți vedea etapele intermediare în diagrama de mai sus. Codul sursă scris de programatori este stocat în fișierul program.c. Acest fișier este apoi procesat de preprocesoare și este generat un fișier de cod sursă extins numit program. Acest fișier extins este compilat de compilator și se generează un fișier de cod obiect numit program .obj. În cele din urmă, linkerul leagă acest fișier de cod obiect cu codul obiect al funcțiilor de bibliotecă pentru a genera fișierul executabil program.exe.
Programele de preprocesare oferă directive de preprocesare care îi spun compilatorului să preproceseze codul sursă înainte de compilare. Toate aceste directive de preprocesor încep cu simbolul ‘#’ (hash). Simbolul ‘#’ indică faptul că, orice instrucțiune care începe cu #, merge la programul preprocesor, iar programul preprocesor va executa această instrucțiune. Iată câteva exemple de directive de preprocesor: #include, #define, #ifndef etc. Nu uitați că simbolul # nu face decât să ofere o cale de acces către preprocesor, iar o comandă precum include este procesată de programul preprocesorului. De exemplu, include va include cod suplimentar în programul dumneavoastră. Putem plasa aceste directive de preprocesor oriunde în programul nostru.
Există 4 tipuri principale de directive de preprocesor:
- Macros
- Includere de fișiere
- Compilare condiționată
- Alte directive
Să cunoaștem acum în detaliu fiecare dintre aceste directive.
- Macros: Macros reprezintă o bucată de cod dintr-un program căreia i se dă un anumit nume. Ori de câte ori acest nume este întâlnit de compilator, compilatorul înlocuiește numele cu bucata de cod reală. Directiva „#define” este utilizată pentru a defini o macro. Să înțelegem acum definiția macro cu ajutorul unui program:
#include <iostream>
#define LIMIT 5
int
main()
{
for
(
int
i = 0; i < LIMIT; i++) {
std::cout << i <<
"\n"
;
}
return
0;
}
#include <stdio.h>
#define LIMIT 5
int
main()
{
for
(
int
i = 0; i < LIMIT; i++) {
printf
(
"%d \n"
,i);
}
return
0;
}
Ieșire:
01234
În programul de mai sus, atunci când compilatorul execută cuvântul LIMIT îl înlocuiește cu 5. Cuvântul „LIMIT” din definiția macro se numește șablon macro, iar „5” este expansiunea macro.
Nota: Nu există punct și virgulă (‘;’) la sfârșitul definiției macro. Definițiile macro nu au nevoie de un punct și virgulă la sfârșit.
Macros cu argumente: Putem, de asemenea, să transmitem argumente la macro-uri. Macrourile definite cu argumente funcționează în mod similar cu funcțiile. Să înțelegem acest lucru cu ajutorul unui program:
#include <iostream>
#define AREA(l, b) (l * b)
int
main()
{
int
l1 = 10, l2 = 5, area;
area = AREA(l1, l2);
std::cout <<
"Area of rectangle is: "
<< area;
return
0;
}
#include <stdio.h>
#define AREA(l, b) (l * b)
int
main()
{
int
l1 = 10, l2 = 5, area;
area = AREA(l1, l2);
printf
(
"Area of rectangle is: %d"
, area);
return
0;
}
Succesiune:
Area of rectangle is: 50
Se poate observa din programul de mai sus că, ori de câte ori compilatorul găsește AREA(l, b) în program, o înlocuiește cu afirmația (l*b) . Nu numai atât, valorile trecute în șablonul macro AREA(l, b) vor fi, de asemenea, înlocuite în instrucțiunea (l*b). Prin urmare, AREA(10, 5) va fi egală cu 10*5.
- Includerea fișierelor: Acest tip de directivă de preprocesor îi spune compilatorului să includă un fișier în programul de cod sursă. Există două tipuri de fișiere care pot fi incluse de către utilizator în program:
- Fișier de antet sau fișiere standard: Aceste fișiere conțin definiția unor funcții predefinite, cum ar fi printf(), scanf() etc. Aceste fișiere trebuie să fie incluse pentru a lucra cu aceste funcții. Funcții diferite sunt declarate în fișiere de antet diferite. De exemplu, funcțiile standard de intrare/ieșire sunt în fișierul „iostream”, în timp ce funcțiile care efectuează operațiuni cu șiruri de caractere sunt în fișierul „string”.
Sintaxa:
- Fișier de antet sau fișiere standard: Aceste fișiere conțin definiția unor funcții predefinite, cum ar fi printf(), scanf() etc. Aceste fișiere trebuie să fie incluse pentru a lucra cu aceste funcții. Funcții diferite sunt declarate în fișiere de antet diferite. De exemplu, funcțiile standard de intrare/ieșire sunt în fișierul „iostream”, în timp ce funcțiile care efectuează operațiuni cu șiruri de caractere sunt în fișierul „string”.
#include< file_name >
unde nume_fișier este numele fișierului care urmează să fie inclus. Parantezele ‘<‘ și ‘>’ îi spun compilatorului să caute fișierul în directorul standard.
- fișiere definite de utilizator: Atunci când un program devine foarte mare, este o bună practică să îl împărțiți în fișiere mai mici și să îl includeți ori de câte ori este nevoie. Aceste tipuri de fișiere sunt fișiere definite de utilizator. Aceste fișiere pot fi incluse ca:
#include"filename"
- Compilare condiționată: Directivele de compilare condiționată sunt un tip de directive care ajută la compilarea unei anumite părți a programului sau la omiterea compilării unei anumite părți a programului în funcție de anumite condiții. Acest lucru se poate face cu ajutorul a două comenzi de preprocesare „ifdef” și „endif”.
Sintaxa:
#ifdef macro_name statement1; statement2; statement3; . . . statementN;#endif
Dacă macroul cu numele ‘macroname’ este definit, atunci blocul de instrucțiuni se va executa normal, dar dacă nu este definit, compilatorul va sări pur și simplu peste acest bloc de instrucțiuni.
- Alte directive: În afară de directivele de mai sus, mai există încă două directive care nu sunt utilizate în mod obișnuit. Acestea sunt:
- Directiva #undef: Directiva #undef este utilizată pentru a nedefini un macro existent. Această directivă funcționează ca:
#undef LIMIT
Utilizând această instrucțiune se va nedefini macroul existent LIMIT. După această instrucțiune, fiecare instrucțiune „#ifdef LIMIT” va fi evaluată la fals.
- #pragma Directivă: Această directivă este o directivă cu scop special și este utilizată pentru a activa sau dezactiva anumite caracteristici. Acest tip de directive sunt specifice compilatorului, adică variază de la un compilator la altul. Unele dintre directivele #pragma sunt discutate mai jos:
- #pragma startup și #pragma exit: Aceste directive ne ajută să specificăm funcțiile care trebuie să ruleze înainte de pornirea programului( înainte ca controlul să treacă la main()) și chiar înainte de ieșirea programului (chiar înainte ca controlul să se întoarcă de la main()).
Nota: Programul de mai jos nu va funcționa cu compilatoarele GCC.
Uitați-vă la programul de mai jos:
- #pragma startup și #pragma exit: Aceste directive ne ajută să specificăm funcțiile care trebuie să ruleze înainte de pornirea programului( înainte ca controlul să treacă la main()) și chiar înainte de ieșirea programului (chiar înainte ca controlul să se întoarcă de la main()).
#include <bits/stdc++.h>
using
namespace
std;
void
func1();
void
func2();
#pragma startup func1
#pragma exit func2
void
func1()
{
cout <<
"Inside func1()\n"
;
}
void
func2()
{
cout <<
"Inside func2()\n"
;
}
int
main()
{
void
func1();
void
func2();
cout <<
"Inside main()\n"
;
return
0;
}
#include <stdio.h>
void
func1();
void
func2();
#pragma startup func1
#pragma exit func2
void
func1()
{
printf
(
"Inside func1()\n"
);
}
void
func2()
{
printf
(
"Inside func2()\n"
);
}
int
main()
{
void
func1();
void
func2();
printf
(
"Inside main()\n"
);
return
0;
}
Scoate:
Inside func1()Inside main()Inside func2()
Codul de mai sus va produce rezultatul de mai jos atunci când este rulat pe compilatoarele GCC:
Inside main()
Acest lucru se întâmplă deoarece GCC nu suportă #pragma startup sau exit. Cu toate acestea, puteți utiliza codul de mai jos pentru o ieșire similară pe compilatoarele GCC.
#include <stdio.h>
void
func1();
void
func2();
void
__attribute__((constructor)) func1();
void
__attribute__((destructor)) func2();
void
func1()
{
printf
(
"Inside func1()\n"
);
}
void
func2()
{
printf
(
"Inside func2()\n"
);
}
int
main()
{
printf
(
"Inside main()\n"
);
return
0;
}
- #pragma warn Directivă: Această directivă este utilizată pentru a ascunde mesajele de avertizare care sunt afișate în timpul compilării.
Putem ascunde avertismentele așa cum se arată mai jos:- #pragma warn -rvl: Această directivă ascunde acele avertismente care sunt afișate atunci când o funcție care ar trebui să returneze o valoare nu returnează o valoare.
- #pragma warn -par: Această directivă ascunde acele avertismente care sunt ridicate atunci când o funcție nu utilizează parametrii care îi sunt trecuți.
- #pragma warn -rch: Această directivă ascunde acele avertismente care sunt ridicate atunci când un cod este inaccesibil. De exemplu: orice cod scris după instrucțiunea return într-o funcție este inaccesibil.
Acest articol este realizat de Harsh Agarwal. Dacă vă place GeeksforGeeks și doriți să contribuiți, puteți, de asemenea, să scrieți un articol folosind contribute.geeksforgeeks.org sau să trimiteți articolul prin e-mail la [email protected]. Vedeți articolul dvs. apărând pe pagina principală GeeksforGeeks și ajutați alți Geeks.
.