czwartek, 26 kwietnia 2018

Język C - Preprocesory

C - Preprocesory

Preprocesor C nie jest częścią kompilatora, ale stanowi oddzielny etap w procesie kompilacji. Mówiąc prościej, preprocesor C jest tylko narzędziem do podstawiania tekstów i instruuje kompilator do wykonania wymaganego przetwarzania wstępnego przed właściwą kompilacją. Odwołujemy się do preprocesora C jako CPP.
Wszystkie polecenia preprocesora zaczynają się od znaku krzyżyka(#). To musi być pierwsza niepusta postać, a dla czytelności, dyrektywa preprocesora powinna rozpoczynać się w pierwszej kolumnie. W poniższej sekcji wymieniono wszystkie ważne dyrektywy preprocesora -
L.p.
Dyrektywa i opis
1
#define
Zastępuje makro preprocesora.
2
#include
Wstawia konkretny nagłówek z innego pliku.
3
#undef
Undefines makr preprocesora.
4
#ifdef
Zwraca true, jeśli to makro jest zdefiniowane.
5
#ifndef
Zwraca wartość true, jeśli to makro nie jest zdefiniowane.
6
#if
Sprawdza, czy warunek czasu kompilacji jest prawdziwy.
7
#else
Alternatywa dla #if.
8
#elif
#else i #if w jednym wyciągu.
9
#endif
Kończy warunkowe przetwarzanie preprocesora.
10
#error
Drukuje komunikat o błędzie na stderr.
11
#pragma
Wydaje specjalne komendy kompilatorowi, używając standardowej metody.

Przykłady preprocesorów

Przeanalizuj poniższe przykłady, aby zrozumieć różne dyrektywy.
#define MAX_ARRAY_LENGTH 20
Dyrektywa ta nakazuje CPP zastąpienie wystąpień MAX_ARRAY_LENGTH na 20. Użyj #define do stałych w celu zwiększenia czytelności.
#include <stdio.h>
#include "myheader.h"
Te dyrektywy mówią CPP, aby pobrać stdio.h z System Libraries i dodać tekst do bieżącego pliku źródłowego. Następny wiersz mówi CPP, aby pobrać myheader.h z lokalnego katalogu i dodać zawartość do bieżącego pliku źródłowego.
#undef  FILE_SIZE
#define FILE_SIZE 42
Informuje CPP o niezdefiniowaniu istniejącego FILE_SIZE i zdefiniowaniu go jako 42.
#ifndef MESSAGE
   #define MESSAGE "Twoje życzenie!"
#endif
Informuje CPP, aby zdefiniował komunikat MESSAGE, tylko jeśli komunikat MESSAGE nie został jeszcze zdefiniowany.
#ifdef DEBUG
   /* Twoje instrukcje debugowania są tutaj */
#endif
Informuje CPP o przetwarzaniu załączonych instrukcji, jeśli zdefiniowano DEBUG. Jest to przydatne, jeśli przekazujesz flagę -DDEBUG do kompilatora gcc w czasie kompilacji. To określi DEBUG, więc możesz włączać i wyłączać debugowanie w locie podczas kompilacji.

Wstępnie zdefiniowane makra

ANSI C definiuje liczbę makr. Chociaż każdy z nich jest dostępny do użycia w programowaniu, wstępnie zdefiniowane makra nie powinny być bezpośrednio modyfikowane.
Sr. no.
Makro i opis
1
__DATA__
Bieżąca data jako literał znaków w formacie "MMM DD YYYY".
2
__TIME__
Aktualny czas jako literał znaków w formacie "HH: MM: SS".
3
__FILE__
Zawiera bieżącą nazwę pliku jako literał łańcuchowy.
4
__LINE__
Zawiera bieżący numer wiersza jako stałą dziesiętną.
5
__STDC__
Zdefiniowany jako 1, gdy kompilator jest zgodny ze standardem ANSI.
Spróbujmy następującego przykładu -

#include <stdio.h>

int main() {

   printf("Plik :%s\n", __FILE__ );
   printf("Data :%s\n", __DATE__ );
   printf("Czas :%s\n", __TIME__ );
   printf("Linia :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );

}
Kiedy powyższy kod w pliku test.c zostanie skompilowany i wykonany, wygeneruje się następujący wynik:
Plik :test.c
Data :Jun 2 2012
Czas :03:36:24
Linia :8
ANSI :1

Operatory preprocesorów

Preprocesor C oferuje następujące operatory do tworzenia makr -

Kontynuacja makra (\) Operator

Makro jest zwykle ograniczone do pojedynczej linii. Operator kontynuacji makra (\) służy do kontynuowania makra, które jest zbyt długie dla pojedynczej linii. Na przykład:
#define  message_for(a, b)  \
   printf(#a " i " #b ": Lubimy ciebie!\n")

Operator ciągu (#)

Operator stringize lub number-sign ("#"), gdy jest używany w definicji makra, konwertuje parametr makra na stałą łańcuchową. Ten operator może być używany tylko w makrze mającym określony argument lub listę parametrów. Na przykład:
#include <stdio.h>

#define  wiadomosc_dla(a, b)  \
   printf(#a " i " #b ": Lubimy ciebie!\n")

int main(void) {
   wiadomosc_dla(Karolina, Dorota);
   return 0;
}
Gdy powyższy kod zostanie skompilowany i wykonany, generuje następujący wynik:
Karolina i Dorota: Lubimy ciebie!

Operator wklejający token (##)

Operator wklejający token (##) w definicji makra łączy dwa argumenty. Pozwala na połączenie dwóch oddzielnych tokenów w definicji makra w jeden token. Na przykład:

#include <stdio.h>

#define tokenwzor(n) printf ("token" #n " = %d", token##n)

int main(void) {
   int token4 = 40;
   tokenwzor(34);
   return 0;
}
Gdy powyższy kod zostanie skompilowany i wykonany, generuje następujący wynik:
token4 = 40
Stało się tak, ponieważ ten przykład powoduje, że rzeczywisty wynik z preprocesora
printf ("token4 = %d", token4);
Przykład ten pokazuje konkatenacji tokena ## n w token4 i tu są stosowane zarówno stringize i token-pasting.

Operator Define()

Operator define jest używany przez preprocesor  w wyrażeniach stałych do określenia, czy identyfikator jest zdefiniowany za pomocą #define. Jeśli określony identyfikator jest zdefiniowany, wartość jest równa (niezerowa). Jeśli symbol nie jest zdefiniowany, wartość jest fałszywa (zero). Zdefiniowany operator jest określony w następujący sposób:
#include <stdio.h>

#if !defined (WIADOMOSC)
   #define WIADOMOSC "Lubimy ciebie!"
#endif

int main(void) {
   printf("Tutaj jest wiadomosc: %s\n", WIADOMOSC); 
   return 0;
}
Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje się następujący wynik:
Tutaj jest wiadomosc: Lubimy ciebie!

Sparametryzowane makra

Jedną z potężnych funkcji CPP jest możliwość symulacji funkcji za pomocą sparametryzowanych makr. Na przykład, możemy mieć jakiś kod do kwadratu liczby w następujący sposób:
int square(int x) {
   return x * x;
}
Możemy przepisać powyższy kod za pomocą makra w następujący sposób:
#define square(x) ((x) * (x))
Makra z argumentami muszą być zdefiniowane za pomocą dyrektywy #define, zanim będą mogły być użyte. Lista argumentów jest ujęta w nawiasy i musi natychmiast następować po nazwie makra. Spacje nie są dozwolone między nazwą makra a nawiasem otwartym. Na przykład:
#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   printf("Wartość Max między 20 a 10 to %d\n", MAX(10, 20)); 
   return 0;
}
Gdy powyższy kod zostanie skompilowany i wykonany, wygeneruje się następujący wynik:
Wartość Max między 20 a 10 to 20


Poprzednia strona                                                          Następna strona


Brak komentarzy:

Prześlij komentarz