C Preprocessors

C Preprocessors

Preprocessors zijn programma's die de broncode verwerken voordat de daadwerkelijke compilatie begint. Ze maken geen deel uit van het compilatieproces, maar werken afzonderlijk, waardoor programmeurs de code vóór het compileren kunnen wijzigen.

  • Het is de eerste stap die de C-broncode doorloopt bij het converteren naar een uitvoerbaar bestand.
  • De belangrijkste soorten preprocessorrichtlijnen zijn:  Macro's Bestandsopname Voorwaardelijke compilatie en andere richtlijnen zoals #undef #pragma etc.
  • Deze richtlijnen worden voornamelijk gebruikt om een ​​bepaald gedeelte van de C-code te vervangen door een andere C-code. Als we bijvoorbeeld '#define PI 3.14' schrijven, wordt PI door de preprocessor vervangen door 3.14.
C Preprocessors

Soorten C-preprocessors

Alle bovenstaande preprocessors kunnen in 4 typen worden ingedeeld:

Macro's

Macro's worden gebruikt om constanten te definiëren of functies te creëren die door de preprocessor worden vervangen voordat de code wordt gecompileerd. De twee preprocessors #definiëren En #undef worden gebruikt om macro's in C te maken en te verwijderen.

#definiëren symbolische waarde
#undef teken

waar na het voorbewerken van de teken zal worden uitgebreid naar zijn waarde in het programma.

Voorbeeld:

C
   #include         // Macro Definition   #define LIMIT 5   int     main  (){      for     (  int     i     =     0  ;     i      <     LIMIT  ;     i  ++  )     {      printf  (  '%d   n  '       i  );      }      return     0  ;   }   

Uitvoer
0 1 2 3 4  

In het bovenstaande programma wordt voordat de compilatie begint het woord LIMIT vervangen door 5. Het woord 'BEPERKEN' in de macrodefinitie wordt een macrosjabloon genoemd En '5' is macro-expansie.

Opmerking Er staat geen puntkomma (;) aan het einde van de macrodefinitie. Macrodefinities hebben geen puntkomma nodig om te eindigen.

Er zijn er ook enkele Vooraf gedefinieerde macro's in C die nuttig zijn bij het bieden van verschillende functionaliteiten aan ons programma.

Een eerder gedefinieerde macro kan gededefinieerd worden met #undef preprocessor. Bijvoorbeeld in de bovenstaande code

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  ;   }   


Uitgang:

 ./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 in  

Macro's met argumenten

We kunnen ook argumenten doorgeven aan macro's. Deze macro's werken op dezelfde manier als functies. Bijvoorbeeld

# definiëren foo(a b) a + b
#define func(r) r * r

Laten we dit begrijpen met een programma:

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  ;   }   

Uitvoer
Area of rectangle is: 50  

Uitleg: In het bovenstaande programma is de macro GEBIED(l b) is gedefinieerd om de oppervlakte van een rechthoek te berekenen door de oppervlakte ervan te vermenigvuldigen lengte (l) En breedte (b) . Wanneer GEBIED(a b) heet het breidt uit naar (een * b) en het resultaat wordt berekend en afgedrukt.

Raadpleeg alstublieft Soorten macro's in C voor meer voorbeelden en typen.

Bestandsopname

Met bestandsopname kunt u externe bestanden (bibliotheken met headerbestanden enz.) in het huidige programma opnemen. Meestal wordt dit gedaan met behulp van de #erbij betrekken richtlijn die zowel systeem- als door de gebruiker gedefinieerde bestanden kan bevatten.

Syntaxis

Er zijn twee manieren om headerbestanden op te nemen.

#erbij betrekken
#erbij betrekken 'bestandsnaam'

De ' <' En '>' haakjes vertel de compiler dat hij naar het bestand moet zoeken in de standaard map terwijl dubbele aanhalingstekens ( '' ) vertel de compiler om te zoeken naar het headerbestand in de directory van het bronbestand.

Voorbeeld:

C
   // Includes the standard I/O library   #include            int     main  ()     {      printf  (  'Hello World'  );          return     0  ;   }   

Uitvoer
Hello World 

Voorwaardelijke compilatie

Voorwaardelijke compilatie Hiermee kunt u delen van de code opnemen of uitsluiten, afhankelijk van bepaalde voorwaarden. Dit is handig voor het maken van platformspecifieke code of voor het opsporen van fouten. Er zijn de volgende voorwaardelijke preprocessor-richtlijnen: #if #ifdef #ifndef else #elif en #endif

Syntaxis

De algemene syntaxis van voorwaardelijke preprocessors is:

#als
// een code
#elif
// nog wat code
#anders
// Nog wat code
#endif

#endif-richtlijn wordt gebruikt om de openingsrichtlijnen #if #ifdef en #ifndef af te sluiten.

Voorbeeld

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 defined  n  '  );   // If PI is not defined check if SQUARE is defined   #elif defined(SQUARE)      printf  (  'Square is defined  n  '  );   // 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  ;   }   

Uitvoer
PI is defined Square is not defined 

Uitleg: Deze code maakt gebruik van voorwaardelijke preprocessorrichtlijnen ( #ifdef #elif en #ifndef ) om te controleren of bepaalde macro's ( PI En VIERKANT ) zijn gedefinieerd. Omdat PI is gedefinieerd, drukt het programma ' PI is gedefinieerd 'controleert vervolgens of SQUARE niet is gedefinieerd en drukt af' Vierkant is niet gedefinieerd '.

Andere richtlijnen

Naast de primaire preprocessorrichtlijnen biedt C ook andere richtlijnen om het gedrag van de compiler en het debuggen te beheren.

#pragma:

Biedt specifieke instructies aan de compiler om zijn gedrag te controleren. Het wordt gebruikt om waarschuwingen uit te schakelen, uitlijning etc.

Syntaxis

#pragma richtlijn

Enkele van de #pragma-richtlijnen worden hieronder besproken: 

  1. #pragma opstarten: Deze richtlijnen helpen ons bij het specificeren van de functies die nodig zijn om te worden uitgevoerd vóór het opstarten van het programma (voordat de besturing overgaat naar main()).
  2. #pragma uitgang : Deze richtlijnen helpen ons de functies te specificeren die nodig zijn om te worden uitgevoerd vlak voordat het programma wordt afgesloten (net voordat het besturingselement terugkeert van main()).

Voorbeeld

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  ;   }   

Uitvoer
Inside main()  

De bovenstaande code produceert de uitvoer zoals hierboven aangegeven wanneer deze wordt uitgevoerd op GCC-compilers terwijl de verwachte uitvoer was:

Verwachte output

 Inside func1() Inside main() Inside func2()   

Dit gebeurt omdat GCC het opstarten of afsluiten van #pragma niet ondersteunt. U kunt de onderstaande code echter gebruiken voor de verwachte uitvoer op GCC-compilers. 

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  ;   }   

Uitvoer
Inside func1() Inside main() Inside func2()  

In het bovenstaande programma hebben we er een aantal gebruikt specifieke syntaxis zodat een van de functies vóór de hoofdfunctie wordt uitgevoerd en de andere na de hoofdfunctie wordt uitgevoerd.

Quiz maken