Претпроцесори су програми који обрађују изворни код пре него што почне стварна компилација. Они нису део процеса компилације, али раде одвојено, дозвољавајући програмерима да модификују код пре компилације.
- То је први корак кроз који пролази Ц изворни код када се конвертује у извршну датотеку.
- Главни типови директива за претпроцесор су Макрои Условна компилација укључивања датотека и друге директиве као што је #ундеф #прагма итд.
- Ове директиве се углавном користе за замену датог дела Ц кода другим Ц кодом. На пример, ако напишемо '#дефине ПИ 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 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; }
Излаз
PI is defined Square is not defined
Објашњење: Овај код користи условне директиве препроцесора ( #ифдеф #елиф и #ифндеф ) да проверите да ли су одређени макрои ( ПИ и СКУАРЕ ) су дефинисани. Пошто је ПИ дефинисан, програм штампа ' ПИ је дефинисан ' затим проверава да КВАДРАТ није дефинисан и штампа ' Квадрат није дефинисан '.
Друге директиве
Осим примарних предпроцесорских директива, Ц такође обезбеђује друге директиве за управљање понашањем компајлера и отклањањем грешака.
#прагма:
Пружа специфична упутства компајлеру да контролише његово понашање. Користи се за онемогућавање поравнања скупова упозорења итд.
Синтакса
#прагма директива
Неке од #прагма директива се разматрају у наставку:
- #прагма стартуп: Ове директиве нам помажу да наведемо функције које су потребне за покретање пре покретања програма (пре него што контрола пређе на маин()).
- #прагма излаз : Ове директиве нам помажу да наведемо функције које су потребне за покретање непосредно пре изласка из програма (непосредно пре него што се контрола врати из маин()).
Пример
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()
У горњем програму користили смо неке специфичне синтаксе тако да се једна од функција извршава пре главне функције, а друга после главне функције.
Креирај квиз