Katedra Elektrotechniki Teoretycznej i Informatyki wykład 12 - sem.iii M. Czyżak
Język C - preprocesor Preprocesor C i C++ (cpp) jest programem, który przetwarza tekst programu przed przekazaniem go kompilatorowi. Można sterować zachowaniem preprocesora stosując odpowiednie polecenia zwane dyrektywami preprocesora.
Język C - preprocesor #include - dyrektywa włączająca tekst innego pliku źródłowego w miejscu jej wystąpienia w pliku podlegającym aktualnie przetwarzaniu #if - dyrektywa kompilacji warunkowej #elif - działa podobnie jak else if w języku C #endif - oznacza koniec bloku kompilacji warunkowej #define - definiuje stałe i makroinstrukcje (pseudofunkcje) #undef - usuwa definicje stałej lub makra #ifdef - znaczy to samo co #if defined( ) #ifndef - znaczy to samo co #if!defined( ) #error - generuje błąd wraz z opisem
Język C - preprocesor Dyrektywy kompilacji warunkowej #if, #else, #elif i #endif #if wyrażenie1 sekwencja instrukcji 1 #elif wyrażenie2 sekwencja instrukcji 2 #elif wyrażenie3 sekwencja instrukcji 3... #elif wyrażenien #endif sekwencja instrukcji N W standardzie ANSI C dyrektywy #if i #elif można zagnieżdżać do co najmniej 8 poziomów, a w C99 do co najmniej 63.
Język C - preprocesor Przykład. Użycie dyrektyw #if, #else, #elif i #endif #define POLSKA 0 #define FRANCJA 1 #define USA 3 #define AKTYWNY_KRAJ USA #if AKTYWNY_KRAJ==USA char waluta[ ]="dolar"; #elif AKTYWNY_KRAJ==FRANCJA char waluta[ ]="euro"; #else AKTYWNY_KRAJ==POLSKA char waluta[ ]="zloty"; #endif
Język C - preprocesor Dyrektywy kompilacji warunkowej #define i #undef Dyrektywy #define i #undef Dyrektywa #define definiuje makro, a dyrektywa usuwa poprzednio zdefiniowaną nazwę makra. Dyrektywy #define ma postać #define makro, a dyrektywa #undef ma postać #undef makro. #define N 5 #define M 5 double tab[n][m] #undef N #undef M // Od tego miejsca N i M nie są zdefiniowane
Język C - preprocesor Dyrektywy #ifdef i #ifndef (cz.1) Dyrektywy te oznaczają odpowiednio " jeśli zdefiniowano" i " jeśli nie zdefiniowano". Ogólna postać dyrektywy #ifdef to #ifdef nazwa_makra sekwencja instrukcji #endif Jeśli nazwa_makra została wcześniej zdefiniowana, wówczas kompilowany jest kod określony jako sekwencja instrukcji.
Język C - preprocesor Dyrektywy #ifdef i #ifndef (cz.2) Ogólna postać dyrektywy #ifndef (oznacza - jeśli nie zdefiniowano) ma formę nastepujacą: #ifndef nazwa_makra sekwencja instrukcji #endif Jeśli nazwa_makra została nie została wcześniej zdefiniowana przy użyciu dyrektywy #define, wówczas kompilowany jest kod określony jako sekwencja instrukcji.
Język C - preprocesor Dyrektywy #ifdef i #ifndef (cz.3) #include <stdio.h> #define STUDENT 1 int main() { #ifdef STUDENT printf(" Witaj\n"); #else printf("witajcie"); #endif #ifndef STUDENT printf("\n STUDENT nie zostal zdefiniowany"); return 0;}
Język C - preprocesor Operator defined Operator ten umożliwia sprawdzenie czy istnieje definicja danej nazwy makra. Ogólna postać stosowania tego operatora to: defined nazwa_makra Jeśli nazwa_makra została zdefiniowana, wyrażenie to ma wartość logiczną prawda, jeżeli nie to ma wartość fałsz. Operator ten można użyć następująco: #if defined FINAL printf("wersja finalna\n"); Do operatora defined można też stosować operator negacji!, wtedy wyrażenie z operatorem defined ma postać!defined.
Język C - preprocesor Dyrektywa #line (cz.1) Dyrektywa #line zmienia zawartość stałych LINE oraz FILE będących predefiniowanymi identyfikatorami kompilatora. Stała LINE zawiera numer aktualnie kompilowanego wiersza kodu. Stała FILE zawiera nazwę aktualnie kompilowanego pliku źródłowego. Dyrektywa jest stosowana w następującej postaci #line numer "nazwa pliku", gdzie numer to dowolna dodatnia liczba całkowita, a nazwa pliku to dowolna poprawna nazwa pliku. numer staje się nową wartością LINE a nazwa pliku staje się nową wartością FILE.
Język C preprocesor Przykład. Zastosowanie #line, LINE i FILE.(cz.1) #include <stdio.h> #include <conio.h> int main(int argc, char* argv[]) { printf("linia programu:%d\n", LINE ); printf("nazwa pliku :%s\n", FILE ); #line 30 "Plik1" printf("linia programu:%d\n", LINE ); printf("nazwa pliku :%s\n", FILE ); getch(); return 0; }
Język C preprocesor Przykład. Zastosowanie #line, LINE i FILE.(cz.2) Wynik działania programu Linia programu:5 Nazwa pliku :C:\Documents and Settings\Administrator\My Documents\Unit1_01122010.cpp Linia programu:30 Nazwa pliku :Plik1
Język C preprocesor Dyrektywa #pragma Dyrektywa o postaci #pragma nazwa_dyrektywy pozwala przekazywać kompilatorowi różnego rodzaju polecenia. W języku C99 dodano operator _Pragma umożliwiający umieszczenie pragmy w inny sposób _Pragma("dyrektywa") Przy użyciu pragmy można wprowadzić polecenia dla konkretnego kompilatora, jeżeli dany kompilator nie pragmy umieszczonej w tekście programu to ją pomija.
Język C preprocesor Przykład. Wybrane dyrektywy #pragma dla kompilatora Borland Builder C++.( cz.1). #pragma argsused Pragma ta jest dozwolona tylko między definicjami funkcji i wpływa na następną definicję funkcji. Wyłącza ona komunikat: "Parameter name is never used in function func-name" #pragma hdrstop Dyrektywa ta kończy listę plików nagłówkowych, które mogą być prekompilowane. Pozwala to zredukować miejsce na dysku używane przez prekompilowane nagłówki.
Język C preprocesor Przykład. Wybrane dyrektywy #pragma dla kompilatora Borland Builder C++. ( cz.2). #pragma startup function-name <priority> #pragma exit function-name <priority> Pragma startup określa funkcję, która jest wywoływana jako pierwsza przed main(), a pragma exit, funkcję która jest wywoływana przed zakończeniem programu przez funkcję _exit(). <priority> może być liczbą z przedziału <64,256>. Funkcje o wyższym priorytecie są wywoływane jako pierwsze przy starcie i jako ostatnie przy wyjściu. Funkcja ta musi być wcześniej zdefiniowana i mieć nagłówek o postaci void fun (void);
Funkcja main() Język C preprocesor Przykład. Proste zastosowanie #pragma startup #include <stdio.h> #include <conio.h> void fun(void) { printf("wywolanie funkcji fun\n"); } #pragma startup fun 100 int main(int argc, char* argv[]) { printf(" Funkcja main()"); getch(); return 0; } Wynik działania programu Wywolanie funkcji fun
Język C preprocesor Operatory preprocesora Operator # Operator ten nazywany jest operatorem tworzenia łańcuchów. Przekształca on poprzedzany argument na tablicę znakową. Przykład. Przekształcenie programu przy użyciu operatora #. #include <stdio.h> #define UtworzLan(s) #s int main(){ printf(utworzlan(lubie C)); return 0; } Program realizowany #include <stdio.h> #define UtworzLan(s) #s int main(){ printf("lubie C"); return 0; }
Język C preprocesor Operatory preprocesora Operator ## Operator ten to operator sklejania łańcuchów. Przykład. Przekształcenie programu przy użyciu operatora ##. #include <stdio.h> #define PolaczLan(a,b) a##b int main(){ int xy=10; printf("%d",polaczlan(x,y)); return 0; } #include <stdio.h> #define PolaczLan(s) a##b int main(){ int xy=10; printf("%d",xy); return 0; }
Język C preprocesor Komentarze W języku ANSI C występuje jeden rodzaj komentarza. Jest to komentarz wielowierszowy rozpoczynający się parą znaków /* i kończący parą */. Kompilator pomija cały tekst znajdujący się między tymi parami znaków. Komentarze takie nie mogą być zagnieżdżane( nie można umieszczać jednego komentarza wewnątrz drugiego). Komentarze takie mogą być umieszczane w programie prawie w każdym miejscu, z wyjątkiem wnętrza słowa kluczowego i identyfikatora. Przykład. /* to jest komentarz poprawny */ swi /* komentarz niepoprawny */tch (ch) { case 1:printf("war1"); break; case 2:printf("war2"); }
Język C preprocesor Komentarze W standardzie C99 istnieje dodatkowo komentarz jednowierszowy w stylu C++ rozpoczynający się parą znaków // i rozciągający się do końca wiersza. Komentarz taki może być umieszczany wewnątrz komentarza wielowierszowego. Przykład. a) // komentarz jednowierszowy b) /* // komentarz zagnieżdżony jednowierszowy... */
Język C Predefiniowane makra W języku ANSI C istnieje pięć predefiniowanych nazw makr: LINE, FILE, DATE, TIME, STDC. Makra LINE i FILE zostały przedstawione poniżej. Makro DATE zawiera łańcuch w postaci miesiąc/dzień/rok reprezentujący datę translacji pliku źródłowego na plik obiektowy. Makro TIME zawiera godzinę kompilacji programu w postaci godzina:minuta:sekunda. Makro STDC zawiera informację o zgodności kompilatora ze standardem C, jeśli jest równe 1, to kompilator jest zgodny ze standardem.