Förprocessorer är program som bearbetar källkoden innan själva kompileringen börjar. De är inte en del av kompileringsprocessen utan fungerar separat så att programmerare kan modifiera koden före kompilering.
- Det är det första steget som C-källkoden går igenom när den konverteras till en körbar fil.
- Huvudtyper av förbearbetningsdirektiv är Makron Villkorlig sammanställning av filinkludering och andra direktiv som #undef #pragma etc.
- Dessa direktiv används främst för att ersätta en given del av C-koden med en annan C-kod. Om vi till exempel skriver '#define PI 3.14' så ersätts PI med 3.14 av förprocessorn.
Typer av C-förprocessorer
Alla ovanstående förprocessorer kan klassificeras i 4 typer:
Makron
Makron används för att definiera konstanter eller skapa funktioner som ersätts av förprocessorn innan koden kompileras. De två förprocessorerna #definiera och #undef används för att skapa och ta bort makron i C.
#definiera symboliskt värde
#undef tecken
där efter förbearbetning tecken kommer att utökas till sin värde i programmet.
Exempel:
C#include // Macro Definition #define LIMIT 5 int main(){ for (int i = 0; i < LIMIT; i++) { printf('%d n' i); } return 0; }
Produktion
0 1 2 3 4
I ovanstående program innan kompileringen börjar ersätts ordet LIMIT med 5. Ordet 'BEGRÄNSA' i makrodefinitionen kallas en makromall och '5' är makroexpansion.
Notera Det finns inget semikolon (;) i slutet av makrodefinitionen. Makrodefinitioner behöver inte ett semikolon för att sluta.
Det finns också några Fördefinierade makron i C som är användbara för att tillhandahålla olika funktioner till vårt program.
Ett makro definierat tidigare kan odefinieras med #undef förprocessor. Till exempel i ovanstående kod
C#include // Macro Definition #define LIMIT 5 // Undefine macro #undef LIMIT int main(){ for (int i = 0; i < LIMIT; i++) { printf('%d n' i); } return 0; }
Produktion:
./Solution.c: In function 'main': ./Solution.c:13:28: error: 'MAX' undeclared (first use in this function) printf('MAX is: %dn' MAX); ^ ./Solution.c:13:28: note: each undeclared identifier is reported only once for each function it appears inMakron Med Argument
Vi kan också skicka argument till makron. Dessa makron fungerar på samma sätt som funktioner. Till exempel
# definiera foo(a b) a + b
#define func(r) r * r
Låt oss förstå detta med ett program:
C#include // macro with parameter #define AREA(l b) (l * b) int main(){ int a = 10 b = 5; // Finding area using above macro printf('%d' AREA(a b)); return 0; }
Produktion
Area of rectangle is: 50
Förklaring: I programmet ovanför makrot OMRÅDE(l b) definieras för att beräkna arean av en rektangel genom att multiplicera dess längd (l) och bredd (b) . När OMRÅDE(a b) kallas det expanderar till (a * b) och resultatet beräknas och skrivs ut.
Vänligen hänvisa Typer av makron i C för fler exempel och typer.
hoppa över listan
Filinkludering
Filinkludering låter dig inkludera externa filer (huvudfilbibliotek etc.) i det aktuella programmet. Detta görs vanligtvis med hjälp av #omfatta direktiv som kan inkludera både system- och användardefinierade filer.
Syntax
Det finns två sätt att inkludera rubrikfiler.
#omfatta
#omfatta 'filnamn'
De '<' och '>' parenteser säg till kompilatorn att leta efter filen i standardkatalog medan dubbla citattecken ( ' ' ) säg till kompilatorn att söka efter rubrikfilen i källfilens katalog.
Exempel:
C// Includes the standard I/O library #include int main() { printf('Hello World'); return 0; }
Produktion
Hello World
Villkorlig sammanställning
Villkorlig sammanställning låter dig inkludera eller exkludera delar av koden beroende på vissa förutsättningar. Detta är användbart för att skapa plattformsspecifik kod eller för felsökning. Det finns följande villkorliga förprocessordirektiv: #if #ifdef #ifndef else #elif och #endif
Syntax
Den allmänna syntaxen för villkorliga förprocessorer är:
#om
// lite kod
#elif
// lite mer kod
#annan
// Lite mer kod
#endif
#endif-direktivet används för att stänga av öppningsdirektiven #if #ifdef och #ifndef.
Exempel
C#include // Defining a macro for PI #define PI 3.14159 int main(){ // Check if PI is defined using #ifdef #ifdef PI printf('PI is definedn'); // If PI is not defined check if SQUARE is defined #elif defined(SQUARE) printf('Square is definedn'); // If neither PI nor SQUARE is defined trigger an error #else #error 'Neither PI nor SQUARE is defined' #endif // Check if SQUARE is not defined using #ifndef #ifndef SQUARE printf('Square is not defined'); // If SQUARE is defined print that it is defined #else printf('Square is defined'); #endif return 0; }
Produktion
PI is defined Square is not defined
Förklaring: Den här koden använder villkorade förbearbetningsdirektiv ( #ifdef #elif och #ifndef ) för att kontrollera om vissa makron ( PI och FYRKANT ) definieras. Eftersom PI är definierad skriver programmet ut ' PI är definierad ' kontrollerar sedan om SQUARE inte är definierat och skriver ut ' Kvadrat är inte definierat '.
Andra direktiv
Förutom de primära förprocessordirektiven tillhandahåller C även andra direktiv för att hantera kompilatorbeteende och felsökning.
#pragma:
Ger specifika instruktioner till kompilatorn för att kontrollera dess beteende. Den används för att inaktivera justering av varningsuppsättningar etc.
Syntax
#pragma direktiv
Några av #pragma-direktiven diskuteras nedan:
- #pragma startup: Dessa direktiv hjälper oss att specificera de funktioner som behövs för att köras innan programmet startar (innan kontrollen går över till main()).
- #pragma utgång : Dessa direktiv hjälper oss att specificera de funktioner som behövs för att köras precis innan programmet avslutas (precis innan kontrollen återvänder från main()).
Exempel
C#include void func1(); void func2(); // specifying funct1 to execute at start #pragma startup func1 // specifying funct2 to execute before end #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; }
Produktion
Inside main()
Ovanstående kod kommer att producera utgången enligt ovan när den körs på GCC-kompilatorer medan den förväntade utgången var:
Förväntad utgång
Inside func1() Inside main() Inside func2() Detta händer eftersom GCC inte stöder #pragma start eller exit. Du kan dock använda koden nedan för den förväntade utdata på GCC-kompilatorer.
C#include 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; }
Produktion
Inside func1() Inside main() Inside func2()
I programmet ovan har vi använt några specifika syntaxer så att en av funktionerna körs före huvudfunktionen och den andra körs efter huvudfunktionen.
Skapa frågesport