DODATEK A PRZEWODNIK JĘZYKA C_________
Mechanizm makrodefinicji przydaje się do definiowania „ważnych stałych”, np.
#define TABSIZE 100 int tablefTABSIZEJ;
Wiersz
#define ABSDIFF(a, b) ((a)>(b) ? (a)-(b): (b)-(a))
definiuje makro zwracające wartość absolutną różnicy jego argumentów. W przeciwieństwie do funkcji, która robi to samo, argumenty makra i zwracana wartość mogą być dowolnego typu arytmetycznego lub nawet mogą być wskaźnikami. Jednak argumenty (a te mogą powodować efekty uboczne) są tu obliczane dwa razy - raz przy porównaniu i drugi raz przy produkowaniu wyniku.
Przy definicji
#define tempfile(dir) #dir 7%s”
#
wywołanie tempfile(/usr/tmp) daje w wyniku "/usr/tmp” 7%s”
co następnie zostanie sklejone w jeden napis. Przy definicji #define cat(x, y) x ## y
wywołanie cat(var,123) produkuje leksem var123. Natomiast wynik wywołania cat(cat(1,2),3) jest nieokreślony: obecność operatora ## zapobiega rozwinięciu argumentów wewnętrznego wywołania. Zatem w efekcie powstanie ciąg leksemów
cat ( 1 , 2 )3
w którym leksem )3 (wynik sklejenia ostatniego leksemu pierwszego argumentu z pierwszym leksemem drugiego) jest niepoprawny.
Po wprowadzeniu makra drugiego poziomu #define xcat(x,y) cat(x,y)
wszystko to działa bardziej przyzwoicie: xcat(xcat(1,2), 3) rzeczywiście tworzy leksem 123, ponieważ w samym xcat nie występuje operator ##.
Podobnie ABSDIFF(ABSDIFF(a,b),c) zgodnie z oczekiwaniem tworzy wynik w pełni rozwinięty.
#
A12 PREPROCESOR _
Wiersz sterujący o postaci # include <nazwa-pliku>
zleca wstawienie w jego miejsce całej zawartości pliku o podanej nazwie. Wśród znaków nazwy pliku nie może wystąpić znak > i znak nowego wiersza, a skutek tej instrukcji jest nieokreślony, jeśli wystąpi któryś ze znaków ”, ’, \ lub para znaków /*. Wskazany plik jest poszukiwany w kilku miejscach zależnych od implementacji.
W przypadku wiersza sterującego o postaci
# include "nazwa-pliku”
plik jest najpierw poszukiwany w miejscu związanym z oryginalnym plikiem źródłowym (wyrażenie celowo zależne od implementacji), a gdy to się nie powiedzie - w tych samych miejscach, co w poprzednim przypadku. Skutek użycia w nazwie pliku znaków ’, \ oraz pary znaków /* jest nadal nieokreślony, ale znak > jest dozwolony.
Na koniec, w wierszu o postaci
# include ciąg-leksemów
różnej od obu poprzednich, ciąg leksemów jest rozwijany w zwykły sposób; w wyniku musi powstać jedna z postaci <...> lub która zostanie zinterpretowana tak, jak opisano powyżej.
Włączanie plików za pomocą #include może być zagnieżdżone.
Fragmenty programu mogą być kompilowane warunkowo, zgodnie z poniższą schematyczną składnią:
kompilacja-warunkowa:
wiersz-if tekst części-elif część-elseopc #endif
wiersz-if:
# if wyraienie-stałe
# ifdef identyfikator
# ifndef identyfikator
części-elif:
wiersz-elif tekst części-elifopc
309