4 FUNKCJE I STRUKTURA PROGRAMU _________
Rozróżnienie deklaracji zmiennej zewnętrznej i jej definicji jest bardzo ważne. Deklaracja informuje o właściwościach zmiennej (przede wszystkim o jej typie); definicja dodatkowo powoduje rezerwację pamięci. Jeśli wiersze
int sp;
double val|MAXVAL];
występują w programie na zewnątrz wszystkich funkcji, to definiują one zmienne zewnętrzne sp i val, powodują przydzielenie wymaganej pamięci, a także są deklaracjami tych zmiennych dla reszty pliku źródłowego. Natomiast wiersze
extern int sp; extern double val[ ];
deklarują reszcie pliku źródłowego, że sp jest zmienną typu int, a val jest tablicą
0 elementach typu double (której rozmiar został gdzieś określony), nie tworzą jednak tych zmiennych ani nie rezerwują dla nich pamięci.
We wszystkich plikach składających się na jeden program źródłowy może wystąpić tylko jedna definicja każdej zmiennej zewnętrznej. Pozostałe pliki mogą zawierać deklaracje extern zapewniające dostęp do takiej zmiennej. (Deklarację extern można umieścić także w pliku zawierającym definicję.) Definicje tablic muszą określać ich rozmiar, natomiast w deklaracjach extem rozmiary nie są obowiązkowe.
Inicjowanie zmiennej zewnętrznej jest możliwe jedynie przy jej definicji.
Funkcje push i pop można zdefiniować w jednym pliku źródłowym, a zmienne val
1 sp zdefiniować i zainicjować w innym (organizacja zupełnie nieodpowiednia dla tego programu). Wówczas, aby powiązać wszystko w całość, należy podać następujące definicje i deklaracje:
W plikul:
extern int sp; extern double val[ ];
void push(double f) { ... }
double pop(void) {... }
W pliku2: int sp = 0;
double val[MAXVAL];
4.5 PLIKI NAGŁÓWKOWE
W plikul deklaracje extern są umieszczone powyżej i na zewnątrz dotyczą więc wszystkich funkcji w pliku; jeden zbiór deklaracji wystarcza na całą zawartość plikul. Taka sama organizacja byłaby wymagana w przypadku, gdy definicje zmiennych sp i val występowałyby w tym samym pliku po ich użyciu.
Rozważmy teraz rozdzielenie fragmentów programu kalkulatora między kilka plików źródłowych tak, jak mogłyby być rozdzielone, gdyby były znacznie większe. Funkcja main mogłaby figurować w jednym pliku nazwanym main.c, funkcje push i pop oraz ich zmienne - w drugim o nazwie stack.c, a funkcja getop - w trzecim, getop.c. Na koniec, czwarty plik źródłowy o nazwie getch.c mógłyby zawierać funkcje getch i ungetch; odłączyliśmy je od pozostałych, gdyż w rzeczywistym programie mogłyby pochodzić z oddzielnie przetłumaczonej biblioteki funkcji.
calc.h:
# define NUMBER ’0' void push(double); double pop(void); int getop(char []); int getch (void); void ungetch (int);
main.c: getop.c: stack.c:
#include <stdio.h> |
# include <stdio.h> |
# include <stdio.h> | ||
#include <stdlib.h> |
# include <ctype.h> |
# include "calc.h" | ||
# include "calc.h” |
# include "calc.h" |
# define MAXVAL 100 | ||
# define MAXOP 100 |
getop() { |
int sp = 0; | ||
main() { |
... |
double val [MAXVAL]; | ||
• • • } |
} |
void push(double) { | ||
... | ||||
} double pop(void) { | ||||
getch.c: |
• # # } | |||
#include <stdio.h>
# define BUFSIZE 100 char buf [BUFSIZE); int bufp = 0; int getch(void) (
}
void ungetch(int) {
• • «
}
117