Ц Препроцесори

Ц Препроцесори

Претпроцесори су програми који обрађују изворни код пре него што почне стварна компилација. Они нису део процеса компилације, али раде одвојено, дозвољавајући програмерима да модификују код пре компилације.

  • То је први корак кроз који пролази Ц изворни код када се конвертује у извршну датотеку.
  • Главни типови директива за претпроцесор су  Макрои Условна компилација укључивања датотека и друге директиве као што је #ундеф #прагма итд.
  • Ове директиве се углавном користе за замену датог дела Ц кода другим Ц кодом. На пример, ако напишемо '#дефине ПИ 3.14', онда је ПИ замењен са 3.14 од стране претпроцесора.
Ц Препроцесори

Типови Ц претпроцесора

Сви горе наведени предпроцесори могу се класификовати у 4 типа:

Макрои

Макрои се користе за дефинисање константи или креирање функција које су замењене претпроцесором пре превођења кода. Два претпроцесора #дефине и #ундеф се користе за креирање и уклањање макроа у Ц.

#дефине вредност токена
#ундеф токен

где је након претходне обраде токен биће проширен на своје вредност у програму.

Пример:

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

Излаз
0 1 2 3 4  

У горњем програму пре почетка компилације реч ЛИМИТ се замењује са 5. Реч 'ЛИМИТ' у макро дефиницији назива се макро шаблон и '5' је проширење макроа.

Напомена Не постоји тачка-зарез (;) на крају макро дефиниције. Макро дефиницијама није потребна тачка и зарез за крај.

Има и неких Унапред дефинисани макрои у Ц који су корисни у пружању различитих функционалности нашем програму.

Макро дефинисан претходно може бити недефинисан коришћењем #ундеф претпроцесора. На пример у горњем коду

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


Излаз:

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

Макрои са аргументима

Такође можемо пренети аргументе макроима. Ови макрои раде слично функцијама. На пример

# дефинисати фоо(а б) а + б
#дефине фунц(р) р * р

Хајде да ово разумемо помоћу програма:

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

Излаз
Area of rectangle is: 50  

Објашњење: У горњем програму макро ПОВРШИНА (л б) је дефинисан за израчунавање површине правоугаоника множењем његовог дужина (л) и ширина (б) . Када ОБЛАСТ (а б) назива се шири на (а * б) а резултат се израчунава и штампа.

Молимо погледајте Врсте макроа у Ц за више примера и типова.

Укључивање датотеке

Укључивање датотека вам омогућава да у тренутни програм укључите екстерне датотеке (библиотеке датотека заглавља итд.). Ово се обично ради помоћу #инцлуде директива која може укључивати и системске и кориснички дефинисане датотеке.

Синтакса

Постоје два начина за укључивање датотека заглавља.

#инцлуде
#инцлуде 'филенаме'

Тхе ' <' и '>' заграде реци компајлеру да потражи датотеку у стандардни именик док двоструки наводници ('') реци компајлеру да тражи датотеку заглавља у директоријуму изворне датотеке.

Пример:

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

Излаз
Hello World 

Цондитионал Цомпилатион

Условна компилација омогућава вам да укључите или искључите делове кода у зависности од одређених услова. Ово је корисно за креирање кода специфичног за платформу или за отклањање грешака. Постоје следеће условне директиве препроцесора: #иф #ифдеф #ифндеф елсе #елиф и #ендиф

Синтакса

Општа синтакса условних предпроцесора је:

#иф
// неки код
#елиф
// још неки код
#елсе
// Још мало кода
#ендиф

Директива #ендиф се користи за затварање директива отварања #иф #ифдеф и #ифндеф.

Пример

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

Излаз
PI is defined Square is not defined 

Објашњење: Овај код користи условне директиве препроцесора ( #ифдеф #елиф и #ифндеф ) да проверите да ли су одређени макрои ( ПИ и СКУАРЕ ) су дефинисани. Пошто је ПИ дефинисан, програм штампа ' ПИ је дефинисан ' затим проверава да КВАДРАТ није дефинисан и штампа ' Квадрат није дефинисан '.

Друге директиве

Осим примарних предпроцесорских директива, Ц такође обезбеђује друге директиве за управљање понашањем компајлера и отклањањем грешака.

#прагма:

Пружа специфична упутства компајлеру да контролише његово понашање. Користи се за онемогућавање поравнања скупова упозорења итд.

Синтакса

#прагма директива

Неке од #прагма директива се разматрају у наставку: 

  1. #прагма стартуп: Ове директиве нам помажу да наведемо функције које су потребне за покретање пре покретања програма (пре него што контрола пређе на маин()).
  2. #прагма излаз : Ове директиве нам помажу да наведемо функције које су потребне за покретање непосредно пре изласка из програма (непосредно пре него што се контрола врати из маин()).

Пример

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

Излаз
Inside main()  

Горњи код ће произвести излаз као што је горе наведено када се покрене на ГЦЦ компајлерима док је очекивани излаз био:

Очекивани излаз

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

Ово се дешава зато што ГЦЦ не подржава #прагма покретање или излаз. Међутим, можете користити доњи код за очекивани излаз на ГЦЦ компајлерима. 

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

Излаз
Inside func1() Inside main() Inside func2()  

У горњем програму користили смо неке специфичне синтаксе тако да се једна од функција извршава пре главне функције, а друга после главне функције.

Креирај квиз