Препроцесори са програми, които обработват изходния код преди да започне същинската компилация. Те не са част от процеса на компилиране, но работят отделно, позволявайки на програмистите да променят кода преди компилация.
- Това е първата стъпка, през която преминава изходният код на C, когато се преобразува в изпълним файл.
- Основните типове директиви за препроцесор са Макроси Условна компилация за включване на файлове и други директиви като #undef #pragma и др.
- Основно тези директиви се използват за замяна на даден раздел от C код с друг C код. Например, ако напишем '#define PI 3.14', тогава PI се заменя с 3.14 от препроцесора.
Видове C препроцесори
Всички горепосочени препроцесори могат да бъдат класифицирани в 4 типа:
Макроси
Макроси се използват за дефиниране на константи или създаване на функции, които се заместват от препроцесора преди кодът да бъде компилиран. Двата препроцесора #дефинирай и #undef се използват за създаване и премахване на макроси в C.
#дефинирай символична стойност
#undef жетон
където след предварителна обработка на жетон ще бъде разширен до своя стойност в програмата.
който е измислил училището
Пример:
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
В горната програма, преди да започне компилацията, думата LIMIT се заменя с 5. Думата „ГРАНИЦА“ в дефиницията на макроса се нарича макро шаблон и '5' е макро разширение.
Забележка Няма точка и запетая (;) в края на дефиницията на макроса. Дефинициите на макроси не се нуждаят от точка и запетая в края.
Има и такива Предварително дефинирани макроси в C които са полезни при предоставянето на различни функционалности на нашата програма.
конвертиране на низ в цяло число
Макрос, дефиниран по-рано, може да бъде недефиниран с помощта на препроцесор #undef. Например в горния код
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Макроси с аргументи
Можем също да предаваме аргументи на макроси. Тези макроси работят подобно на функциите. например
# дефинирам foo(a b) a + b
#define func(r) r * r
Нека разберем това с програма:
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
Обяснение: В горната програма макросът се дефинира за изчисляване на площта на правоъгълник чрез умножаване на неговата дължина (l) и ширина (б) . Кога ПЛОЩ (a b) се нарича разширява се до (a * b) и резултатът се изчислява и отпечатва.
base64 декодиране в js
Моля, направете справка Видове макроси в C за повече примери и типове.
Включване на файл
Включването на файлове ви позволява да включвате външни файлове (библиотеки със заглавни файлове и т.н.) в текущата програма. Това обикновено се прави с помощта на #включи директива, която може да включва както системни, така и дефинирани от потребителя файлове.
Синтаксис
Има два начина за включване на заглавни файлове.
#включи
#включи име на файл
The '<' и '>' скоби кажете на компилатора да потърси файла в стандартна директория докато двойни кавички ( ' ' ) кажете на компилатора да търси заглавния файл в директорията на изходния файл.
Пример:
C// Includes the standard I/O library #include int main() { printf('Hello World'); return 0; }
Изход
Hello World
Условна компилация
Условна компилация ви позволява да включвате или изключвате части от кода в зависимост от определени условия. Това е полезно за създаване на специфичен за платформа код или за отстраняване на грешки. Има следните условни директиви за препроцесор: #if #ifdef #ifndef else #elif и #endif
Синтаксис
Общият синтаксис на условните препроцесори е:
#ако
// някакъв код
#елиф
// още малко код
#друго
// Още малко код
#endif
Директивата #endif се използва за затваряне на отварящите директиви #if #ifdef и #ifndef.
град в САЩ
Пример
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
Обяснение: Този код използва условни директиви за препроцесор ( #ifdef #elif и #ifndef ), за да проверите дали някои макроси ( ПИ и КВАДРАТ ) са определени. Тъй като PI е дефиниран, програмата отпечатва ' PI е дефиниран ' след това проверява дали SQUARE не е дефиниран и отпечатва ' Квадратът не е дефиниран '.
Други директиви
Освен директивите за първичен препроцесор, C предоставя и други директиви за управление на поведението на компилатора и отстраняване на грешки.
#прагма:
Предоставя конкретни инструкции на компилатора, за да контролира поведението му. Използва се за деактивиране на подравняване на набор от предупреждения и др.
Синтаксис
#прагма директива
Някои от директивите #pragma са разгледани по-долу:
- #pragma стартиране: Тези директиви ни помагат да уточним функциите, които са необходими за изпълнение преди стартиране на програмата (преди управлението да премине към main()).
- #pragma изход : Тези директиви ни помагат да посочим функциите, които са необходими за изпълнение точно преди изхода на програмата (точно преди контролата да се върне от main()).
Пример
иначе ако javaC
#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()
Горният код ще произведе изхода, както е даден по-горе, когато се изпълнява на GCC компилатори, докато очакваният изход е:
Очакван резултат
Inside func1() Inside main() Inside func2() Това се случва, защото GCC не поддържа #pragma стартиране или излизане. Въпреки това можете да използвате кода по-долу за очаквания изход на компилаторите на GCC.
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()
В горната програма сме използвали някои специфичен синтаксис така че една от функциите да се изпълнява преди основната функция, а другата да се изпълнява след основната функция.
Създаване на тест