logo

Preprocesory C

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.
Preprocesory C

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 in

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

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: 

  1. #pragma uruchomienie: Dyrektywy te pomagają nam określić funkcje, które są potrzebne do uruchomienia przed uruchomieniem programu (zanim kontrola przejdzie do main()).
  2. #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