4 FUNKCJE I STRUKTURA PROGRAMU
Jest jeszcze jedna rzecz, o którą należy się zatroszczyć - wspólne definicje i deklaracje dla wszystkich plików. Chcemy je wszystkie zgromadzić w jednym miejscu tak, aby występowała tylko jedna kopia każdej z nich, teraz i w przyszłości, kiedy będziemy rozwijać program. A zatem te wspólne dane umieścimy w pliku nagłówkowym o nazwie calc.h i będziemy go włączać w razie potrzeby. (Wiersz #include jest dokładniej opisany w p. 4.11.) Program wynikowy wygląda więc tak, jak to pokazano na str. 117.
Występuje pewna sprzeczność między wymaganiem, aby z każdego pliku źródłowego mieć dostęp jedynie do tych informacji, które są niezbędne do działania, a praktycznym realizmem, z którego wynika, że trudniej jest utrzymywać porządek w wielu plikach nagłówkowych. Do pewnego średniego rozmiaru programu prawdopodobnie najlepszą metodą jest opracowanie jednego pliku nagłówkowego, w którym mieści się wszystko to, co może być wspólne dla dowolnych dwóch części programu; taką właśnie decyzję podjęliśmy w naszym przykładzie. Dużo większe programy wymagają więcej prac organizacyjnych i większej liczby nagłówków.
t
Zmienne sp i val w pliku źródłowym stack.c oraz zmienne buf i bufp w pliku getch.c zdefiniowano na wyłączny użytek odpowiednich funkcji z tych plików źródłowych; nie zamierzano udostępnić ich innym funkcjom. Deklaracja static zastosowana do zmiennych zewnętrznych i funkcji ogranicza ich zasięg od miejsca wystąpienia do końca tłumaczonego pliku źródłowego. Deklarowanie zewnętrznych obiektów jako static jest więc sposobem na ukrycie ich nazw. Na przykład zmienne buf i bufp muszą być zewnętrzne, aby mogły być wspólne dla pary funkcji getch-ungetch, powinny jednak być niewidoczne dla użytkowników tych funkcji.
Pamięć statyczną określa się przez poprzedzenie normalnej deklaracji słowem kluczowym static. Jeśli obie funkcje i obie zmienne zostaną umieszczone w jednym pliku źródłowym, np.
static char buf[BUFSIZE]; /* bufor na zwroty z ungetch */ static int bufp = 0; /* następne wolne miejsce w buf */
int getch(void) {...}
void ungetch(int c) (...)
to żadna inna funkcja nie będzie miała dostępu do zmiennych buf i bufp, a ich naz'*') nie będą kolidować z takimi samymi nazwami w innych plikach tego samego progf3'
4.7 ZMIENNE REJESTROWE
mTśioI
mu. W ten sam sposób można ukryć zmienne sp i val, z których push i pop przy obsłudze stosu: wystarczy zadeklarować je jako static.
Zewnętrzną deklarację static najczęściej stosuje się dó zmiennych, ale można ją także stosować do funkcji. Nazwy funkcji są zwykle globalne, widoczne dla wszystkich części całego programu. Jeśli jednak funkcję zadeklarowano jako Static, jej nazwa staje się niewidzialna poza plikiem zawierającym jej deklarację.
Deklarację static można również stosować do zmiennych wewnętrznych. Wewnętrzne zmienne statyczne są lokalne dla poszczególnych funkcji tak samo, jak zmienne automatyczne. Jednak w przeciwieństwie do automatycznych nie pojawiają się i nie znikają razem z wywołaniem funkcji, lecz istnieją między jej wywołaniami. To znaczy, że wewnętrzne zmienne static stanowią prywatną, stałą pamięć wewnątrz pojedynczej funkcji.
Ćwiczenie 4.11. Zmień funkcję getop tak, aby nie potrzebowała funkcji ungetch. Rada: użyj wewnętrznej zmiennej static.
Deklaracja register powiadamia kompilator o tym, że zmienna, której ta deklaracja dotyczy, będzie intensywnie używana. Pomysł polega na tym, aby takie zmienne register umieszczać w rejestrach maszyny, co w efekcie może zmniejszyć i przyspieszyć programy. Kompilatory mogą jednak tę informację zignorować.
Oto typowa deklaracja register:
register int x; register char c;
Deklarację register można stosować jedynie do zmiennych automatycznych i do formalnych parametrów funkcji. W tym ostatnim przypadku deklaracja ma postać:
f(register unsigned m, register long n)
register int i;
W praktyce, przy korzystaniu ze zmiennych rejestrowych występują pewne ograniczenia odzwierciedlające rzeczywiste możliwości dostępnego sprzętu. Każda funkcja może przechowywać w rejestrach tylko kilka zmiennych, ponadto nie wszystkie ich typy są dozwolone. Nadliczbowe deklaracje zmiennych rejestrowych są jednak nieszkodliwe,
119