logo

Preprocesory C

Preprocesory to programy przetwarzające kod źródłowy przed kompilacją. Pomiędzy napisaniem programu a wykonaniem programu w C składa się z kilku kroków. Przyjrzyjmy się tym krokom, zanim zaczniemy poznawać preprocesory.

preprocesory w c



Etapy pośrednie można zobaczyć na powyższym schemacie. Kod źródłowy napisany przez programistów jest najpierw przechowywany w pliku, niech tak zostanie nazwana program.c . Plik ten jest następnie przetwarzany przez preprocesory i generowany jest rozszerzony plik kodu źródłowego o nazwie program.i. Ten rozwinięty plik jest kompilowany przez kompilator i generowany jest plik kodu obiektowego o nazwie program.obj. Na koniec linker łączy ten plik kodu obiektowego z kodem wynikowym funkcji bibliotecznych w celu wygenerowania pliku wykonywalnego program.exe.

Dyrektywy preprocesora w C

Programy preprocesora udostępniają dyrektywy preprocesora, które nakazują kompilatorowi wstępne przetworzenie kodu źródłowego przed kompilacją. Wszystkie te dyrektywy preprocesora zaczynają się od symbolu „#” (hash). Symbol „#” oznacza, że ​​instrukcja rozpoczynająca się od „#” zostanie skierowana do programu preprocesora w celu wykonania. Możemy umieścić te dyrektywy preprocesora w dowolnym miejscu naszego programu.

Przykładami niektórych dyrektyw preprocesora są: #włączać , #definiować , #ifndef, itp.



Notatka Pamiętaj, że # symbol zapewnia jedynie ścieżkę do preprocesora, a polecenie takie jak include jest przetwarzane przez program preprocesora. Na przykład #include uwzględni kod lub zawartość określonego pliku w programie.

Lista dyrektyw preprocesora w C

Poniższa tabela zawiera listę wszystkich dyrektyw preprocesora w języku C:

Dyrektywy preprocesora

Opis



#definiować

Służy do definiowania makra

#undef

Służy do cofania definicji makra

#włączać

Służy do dołączania pliku do kodu źródłowego programu

#ifdef

Służy do dołączania sekcji kodu, jeśli określone makro jest zdefiniowane przez #define

#ifndef

Służy do dołączania sekcji kodu, jeśli określone makro nie jest zdefiniowane przez #define

#Jeśli

Sprawdź określony warunek

#w przeciwnym razie

Alternatywny kod, który jest wykonywany, gdy #if zakończy się niepowodzeniem

#endif

Używane do oznaczania końca #if, #ifdef i #ifndef

Te preprocesory można sklasyfikować na podstawie rodzaju wykonywanej funkcji.

Rodzaje preprocesorów C

Istnieją 4 główne typy dyrektyw preprocesora:

  1. Makra
  2. Dołączenie pliku
  3. Kompilacja warunkowa
  4. Inne dyrektywy

Przyjrzyjmy się teraz szczegółowo każdej z tych dyrektyw.

1. Makra

W języku C makra są fragmentami kodu programu, któremu nadano jakąś nazwę. Ilekroć kompilator napotyka tę nazwę, kompilator zastępuje ją rzeczywistym fragmentem kodu. The '#definiować' dyrektywa służy do definiowania makra.

Składnia definicji makra

  #define     token     value>

gdzie po wstępnej obróbce, znak zostanie rozszerzony do swojego wartość w programie.

Przykład Makro

C




// C Program to illustrate the macro> #include> // macro definition> #define LIMIT 5> int> main()> {> >for> (>int> i = 0; i printf('%d ', i); } return 0; }>

subskrypcja lazurowa
>

>

Wyjście

0 1 2 3 4>

W powyższym programie, gdy kompilator wykonuje słowo LIMIT, zastępuje je liczbą 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.

Makra z argumentami

Możemy także przekazywać argumenty do makr. Makra definiowane za pomocą argumentów działają podobnie do funkcji.

Przykład

  #define   foo(  a, b  )   a + b  #define func(r) r * r>

Rozumiemy to za pomocą programu:

C




// C Program to illustrate function like macros> #include> // macro with parameter> #define AREA(l, b) (l * b)> int> main()> {> >int> l1 = 10, l2 = 5, area;> >area = AREA(l1, l2);> >printf>(>'Area of rectangle is: %d'>, area);> >return> 0;> }>

Java konwertuje na ciąg
>

>

Wyjście

Area of rectangle is: 50>

Z powyższego programu widać, że ilekroć kompilator znajdzie w programie AREA(l, b), zastępuje go instrukcją (l*b). Nie tylko to, ale wartości przekazane do szablonu makra AREA(l, b) również zostaną zastąpione w instrukcji (l*b). Zatem POLE(10, 5) będzie równe 10*5.

2. Dołączenie pliku

Ten typ dyrektywy preprocesora mówi kompilatorowi, aby umieścił plik w kodzie źródłowym programu. The #include dyrektywa preprocesora służy do dołączania plików nagłówkowych do programu C.

Istnieją dwa typy plików, które użytkownik może zawrzeć w programie:

Standardowe pliki nagłówkowe

Standardowe pliki nagłówkowe zawierają definicje predefiniowanych funkcji, takich jak printf(), scanf(), itp. Aby móc korzystać z tych funkcji, należy dołączyć te pliki. Różne funkcje są deklarowane w różnych plikach nagłówkowych.
Na przykład standardowe funkcje we/wy znajdują się w pliku „iostream”, natomiast funkcje wykonujące operacje na łańcuchach znaków znajdują się w pliku „string”.

Składnia

  #include   <  file_name>>

Gdzie Nazwa pliku to nazwa pliku nagłówkowego, który ma zostać dołączony. The „nawiasy”. powiedz kompilatorowi, aby szukał pliku w s katalog standardowy.

Zdefiniowane przez użytkownika pliki nagłówkowe

Kiedy program staje się bardzo duży, dobrą praktyką jest podzielenie go na mniejsze pliki i dołączenie ich w razie potrzeby. Tego typu pliki to pliki nagłówkowe zdefiniowane przez użytkownika.

Składnia

  #include   '  filename  '>

The podwójne cudzysłowy ( ) powiedz kompilatorowi, aby wyszukał plik nagłówkowy w katalog pliku źródłowego.

3. Kompilacja warunkowa

Kompilacja warunkowa w dyrektywach C to rodzaj dyrektywy, która pomaga skompilować określoną część programu lub pominąć kompilację określonej części programu w oparciu o pewne warunki. Istnieją następujące dyrektywy preprocesora używane do wstawiania kodu warunkowego:

  1. #if dyrektywa
  2. Dyrektywa #ifdef
  3. Dyrektywa #ifndef
  4. #else Dyrektywa
  5. Dyrektywa #elif
  6. Dyrektywa #endif

#endif Dyrektywa służy do zamykania dyrektyw otwierających #if, #ifdef i #ifndef, co oznacza, że ​​wstępne przetwarzanie tych dyrektyw zostało zakończone.

Składnia

  #ifdef     macro_name   // Code to be executed if macro_name is defined #  ifndef     macro_name   // Code to be executed if macro_name is not defined   #if    constant_expr   // Code to be executed if constant_expression is true   #elif     another_constant_expr   // Code to be excuted if another_constant_expression is true   #else   // Code to be excuted if none of the above conditions are true   #endif>

Jeżeli makro o nazwie „ nazwa_makra ' jest zdefiniowany, wówczas blok instrukcji zostanie wykonany normalnie, ale jeśli nie zostanie zdefiniowany, kompilator po prostu pominie ten blok instrukcji.

Przykład

Poniższy przykład ilustruje użycie dyrektyw preprocesora #include #if, #elif, #else i #endif.

C




//program to demonstrates the use of #if, #elif, #else,> // and #endif preprocessor directives.> #include> // defining PI> #define PI 3.14159> int> main()> {> > #ifdef PI> >printf>(>'PI is defined '>);> > #elif defined(SQUARE)> >printf>(>'Square is defined '>);> #else> >#error 'Neither PI nor SQUARE is defined'> #endif> > #ifndef SQUARE> >printf>(>'Square is not defined'>);> #else> >cout <<>'Square is defined'> << endl;> #endif> >return> 0;> }>

>

>

Wyjście

PI is defined Square is not defined>

4. Inne dyrektywy

Oprócz powyższych dyrektyw istnieją jeszcze dwie dyrektywy, które nie są powszechnie stosowane. To są:

  1. Dyrektywa #undef
  2. Dyrektywa #pragma

1. Dyrektywa #undef

Dyrektywa #undef służy do cofania definicji istniejącego makra. Dyrektywa ta działa jako:

#undef LIMIT>

Użycie tej instrukcji spowoduje anulowanie definicji istniejącego makra LIMIT. Po tej instrukcji każda instrukcja #ifdef LIMIT będzie oceniana jako fałszywa.

Przykład

Poniższy przykład ilustruje działanie dyrektywy #undef.

lista czcionek gimp

C




#include> // defining MIN_VALUE> #define MIN_VALUE 10> int> main() {> >// Undefining and redefining MIN_VALUE> printf>(>'Min value is: %d '>,MIN_VALUE);> > //undefining max value> #undef MIN_VALUE> > // again redefining MIN_VALUE> #define MIN_VALUE 20> >printf>(>'Min value after undef and again redefining it: %d '>, MIN_VALUE);> >return> 0;> }>

>

>

Wyjście

Min value is: 10 Min value after undef and again redefining it: 20>

2. Dyrektywa #pragma

Ta dyrektywa jest dyrektywą specjalnego przeznaczenia i służy do włączania lub wyłączania niektórych funkcji. Tego typu dyrektywy są specyficzne dla kompilatora, tj. różnią się w zależności od kompilatora.

Składnia

#pragma   directive>

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 zakończeniem programu (tuż przed powrotem sterowania z funkcji main()).

Poniższy program nie będzie działał z kompilatorami GCC.

Przykład

Poniższy program zilustruj użycie wyjścia #pragma i uruchomienia pragmy

C




// C program to illustrate the #pragma exit and pragma> // startup> #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() '>); }> void> func2() {>printf>(>'Inside func2() '>); }> // driver code> int> main()> {> >void> func1();> >void> func2();> >printf>(>'Inside main() '>);> >return> 0;> }>

>

>

Oczekiwany wynik

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

Powyższy kod wygeneruje dane wyjściowe podane poniżej, gdy zostanie uruchomiony na kompilatorach GCC:

Inside main()c>

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.

znak do int Java

C




#include> void> func1();> void> func2();> void> __attribute__((constructor)) func1();> void> __attribute__((destructor)) func2();> void> func1()> {> >printf>(>'Inside func1() '>);> }> void> func2()> {> >printf>(>'Inside func2() '>);> }> int> main()> {> >printf>(>'Inside main() '>);> >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.

#pragma ostrzega dyrektywę

Ta dyrektywa służy do ukrycia komunikatu ostrzegawczego wyświetlanego podczas kompilacji. Możemy ukryć ostrzeżenia, jak pokazano poniżej:

  • #pragma ostrzegaj -rvl : Ta dyrektywa ukrywa ostrzeżenia, które są wywoływane, gdy funkcja, która powinna zwracać wartość, nie zwraca wartości.
  • #pragma ostrzegaj -par : Ta dyrektywa ukrywa ostrzeżenia, które są generowane, gdy funkcja nie korzysta z przekazanych jej parametrów.
  • #pragma ostrzegaj -rch : Ta dyrektywa ukrywa ostrzeżenia, które są generowane, gdy kod jest nieosiągalny. Na przykład dowolny kod napisany po powrót instrukcja w funkcji jest nieosiągalna.

Jeśli podoba Ci się techcodeview.com i chciałbyś wnieść swój wkład, możesz także napisać artykuł za pomocą . Zobacz, jak Twój artykuł pojawia się na stronie głównej techcodeview.com i pomóż innym Geekom. Napisz komentarz, jeśli znajdziesz coś nieprawidłowego lub jeśli chcesz podzielić się więcej informacjami na temat omówiony powyżej.