Preprocesory to programy, które przetwarzają kod źródłowy przed rozpoczęciem właściwej kompilacji. Nie są one częścią procesu kompilacji, ale działają oddzielnie, umożliwiając programistom modyfikację kodu przed kompilacją.
- Jest to pierwszy krok, przez który przechodzi kod źródłowy C podczas konwersji do pliku wykonywalnego.
- Główne typy dyrektyw preprocesora to Makra Kompilacja warunkowa dołączania plików i inne dyrektywy, takie jak #undef #pragma itp.
- Głównie te dyrektywy służą do zastąpienia danej sekcji kodu C innym kodem C. Na przykład, jeśli napiszemy „#define PI 3.14”, wówczas preprocesor zastąpi PI numerem 3.14.
Rodzaje preprocesorów C
Wszystkie powyższe preprocesory można podzielić na 4 typy:
Makra
Makra służą do definiowania stałych lub tworzenia funkcji, które są zastępowane przez preprocesor przed skompilowaniem kodu. Dwa preprocesory #określić I #undef służą do tworzenia i usuwania makr w języku C.
#określić wartość tokenu
#undef znak
gdzie po wstępnej obróbce znak zostanie rozszerzony do swojego wartość w programie.
subskrypcja lazurowa
Przykład:
C#include // Macro Definition #define LIMIT 5 int main(){ for (int i = 0; i < LIMIT; i++) { printf('%d n' i); } return 0; }
Wyjście
0 1 2 3 4
W powyższym programie przed rozpoczęciem kompilacji słowo LIMIT zostaje zastąpione przez 5. Słowo 'LIMIT' w definicji makro nazywa się szablonem makra I „5” to ekspansja makro.
Notatka Na końcu definicji makra nie ma średnika (;). Definicje makr nie wymagają średnika na końcu.
Są też tacy Predefiniowane makra w C które są przydatne w zapewnianiu różnych funkcjonalności naszego programu.
Makro zdefiniowane wcześniej można niezdefiniować przy użyciu preprocesora #undef. Na przykład w powyższym kodzie
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; }
Wyjście:
./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 inMakra z argumentami
Możemy także przekazywać argumenty do makr. Makra te działają podobnie do funkcji. Na przykład
Java konwertuje na ciąg
# określić foo(a b) a + b
#zdefiniuj funkcję(r) r * r
Rozumiemy to za pomocą programu:
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; }
Wyjście
Area of rectangle is: 50
Wyjaśnienie: W powyższym programie makro POWIERZCHNIA(lb) definiuje się do obliczania pola prostokąta poprzez pomnożenie jego długość (l) I szerokość (b) . Gdy POWIERZCHNIA(ab) nazywa się to rozszerza się do (a * b) a wynik jest obliczany i drukowany.
Proszę zapoznać się Rodzaje makr w C aby uzyskać więcej przykładów i typów.
Dołączenie pliku
Dołączanie plików umożliwia dołączenie plików zewnętrznych (biblioteki plików nagłówkowych itp.) do bieżącego programu. Zwykle odbywa się to za pomocą #włączać dyrektywa, która może zawierać zarówno pliki systemowe, jak i pliki zdefiniowane przez użytkownika.
Składnia
Istnieją dwa sposoby dołączania plików nagłówkowych.
#włączać
#włączać „nazwa pliku”
The '<' I nawiasy „>”. powiedz kompilatorowi, aby szukał pliku w standardowy katalog chwila podwójne cudzysłowy ( ' ' ) powiedz kompilatorowi, aby wyszukał plik nagłówkowy w katalogu pliku źródłowego.
Przykład:
C// Includes the standard I/O library #include int main() { printf('Hello World'); return 0; }
Wyjście
Hello World
Kompilacja warunkowa
Kompilacja warunkowa pozwala na włączenie lub wykluczenie części kodu w zależności od określonych warunków. Jest to przydatne do tworzenia kodu specyficznego dla platformy lub do debugowania. Istnieją następujące dyrektywy preprocesora warunkowego: #if #ifdef #ifndef else #elif i #endif
Składnia
Ogólna składnia preprocesorów warunkowych jest następująca:
lista czcionek gimp
#Jeśli
// jakiś kod
#elif
// trochę więcej kodu
#w przeciwnym razie
// Jeszcze trochę kodu
#endif
Dyrektywa #endif służy do zamykania dyrektyw otwierających #if #ifdef i #ifndef.
Przykład
znak do int JavaC
#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; }
Wyjście
PI is defined Square is not defined
Wyjaśnienie: W kodzie tym zastosowano dyrektywy warunkowe preprocesora ( #ifdef #elif i #ifndef ), aby sprawdzić, czy określone makra ( LICZBA PI I KWADRAT ) są zdefiniowane. Ponieważ zdefiniowano PI, program wypisuje „ PI jest zdefiniowane 'następnie sprawdza, czy SQUARE nie jest zdefiniowany i wypisuje ' Kwadrat nie jest zdefiniowany '.
Inne dyrektywy
Oprócz podstawowych dyrektyw preprocesora C udostępnia także inne dyrektywy służące do zarządzania zachowaniem kompilatora i debugowaniem.
#pragma:
Dostarcza kompilatorowi szczegółowe instrukcje umożliwiające kontrolowanie jego zachowania. Służy do wyłączania ostrzeżeń, ustawiania wyrównania itp.
Składnia
#pragma dyrektywa
Niektóre z dyrektyw #pragma omówiono poniżej:
- #pragma uruchomienie: Dyrektywy te pomagają nam określić funkcje, które są potrzebne do uruchomienia przed uruchomieniem programu (zanim kontrola przejdzie do main()).
- #pragma wyjście : Te dyrektywy pomagają nam określić funkcje, które są potrzebne do uruchomienia tuż przed wyjściem programu (tuż przed powrotem sterowania z funkcji main()).
Przykład
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; }
Wyjście
Inside main()
Powyższy kod wygeneruje dane wyjściowe podane powyżej, gdy zostanie uruchomiony na kompilatorach GCC, podczas gdy oczekiwany wynik będzie następujący:
Oczekiwany wynik
Inside func1() Inside main() Inside func2() Dzieje się tak, ponieważ GCC nie obsługuje uruchamiania lub zamykania #pragma. Możesz jednak użyć poniższego kodu dla oczekiwanych wyników w kompilatorach 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; }
Wyjście
Inside func1() Inside main() Inside func2()
W powyższym programie użyliśmy niektórych specyficzne składnie tak, że jedna z funkcji jest wykonywana przed funkcją główną, a druga po funkcji głównej.
Utwórz quiz