3 STEROWANIE
Dla przykładu rozważmy problem: jak zbadać, czy w dwóch tablicach a i b występuje taki sam element. Jednym z rozwiązań może być:
for (i = 0; i < n; i++) for 0 = 0; j < m; j++) if (a[i] == b[j])
goto found; /* znaleziony */
/* nie ma takiego elementu */
• • •
found: /* znaleziony: a[i] == b[jj */
• • •
Program zawierający instrukcję goto zawsze można napisać bez niej, chociaż prawdopodobnie kosztem kilku powtórzonych sprawdzeń i dodatkowych zmiennych. Powyższy przykład przeszukiwania tablic może zatem wyglądać następująco:
found = 0;
for (i = 0; i < n && ifound; i-H-) for (j = 0; j < m && ifound; j++) if (a[i] == bfj]) found = 1;
if (found)
I* znaleziony: a[i] == b[j] */
• • • else
I* nie ma takiego elementu */
• • •
Program, który skonstruowano za pomocą instrukcji goto (z paroma wyjątkami, jak te omówione), zazwyczaj trudniej jest zrozumieć i aktualizować niż program bez tych instrukcji. Nie jesteśmy w tej sprawie dogmatyczni, wydaje się jednak, że jeśli instrukcja goto ma być w ogóle stosowana, to powinna być stosowana rzadko.
Funkcje pomagają podzielić duże przedsięwzięcia obliczeniowe na mniejsze zadania. Dzięki nim można korzystać z tego, co już zostało przez innych zrobione, zamiast rozpoczynać zawsze od zera. Odpowiednie funkcje ukrywają szczegóły pewnych operacji przed częściami programu, w których znajomość tych szczegółów jest zbędna. Całość jest wówczas bardziej przejrzysta, a ponadto łatwiej wprowadza się zmiany.
Język C opracowano tak, aby posługiwanie się funkcjami było wygodne i skuteczne. Na ogół programy w języku C składają się z wielu małych funkcji, a nie z kilku dużych. Każdy program można umieścić w jednym lub kilku plikach źródłowych. Pliki te mogą być tłumaczone oddzielnie i ładowane razem z funkcjami, które zostały uprzednio przetłumaczone i umieszczone w bibliotekach. Nie będziemy jednak tutaj wnikać w szczegóły tego procesu, zmieniają się one bowiem w zależności od dostępnego systemu.
Deklaracje i definicje funkcji stanowią dziedzinę, w której standard ANSI przeprowadził najbardziej widoczne zmiany. Jak pokazaliśmy w rozdz. 1, można teraz deklarować typy argumentów przy deklaracji funkcji. Zmieniła się też składnia definicji funkcji tak, aby deklaracje i definicje były zgodne. Dzięki temu kompiltor potrafi wykryć dużo więcej błędów niż dotychczas. Co więcej, jeśli parametry zadeklarowano poprawnie, to odpowiednie przekształcenia typów argumentów są wykonywane automatycznie.
W standardzie wyjaśniono reguły dotyczące zasięgu nazw; w szczególności wymaga się dokładnie jednej definicji każdego obiektu zewnętrznego. Inicjowanie stało się ogólniejsze: można teraz nadawać wartości początkowe automatycznym tablicom i strukturom.
Rozszerzono także zakres możliwości preprocesora C. Do nowych właściwości preprocesora należą: pełniejszy zbiór poleceń dla kompilacji warunkowej, możliwość sklejania argumentów tekstowych w makrach oraz lepsza kontrola samego procesu rozwijania makr.
99