Kris Jamsa Wygraj Z C++ lekcja36


Lekcja 37LEKCJA 37
Używanie stałych i makr
Aby zwiększyć czytelność swoich programów, możesz używać nazw stałych i makr.
Korzystając z nazw stałych możesz na przykład zastępować w kodzie źródłowym
wartości liczbowe, takie jak 50, znaczącymi stałymi, takimi jak WIELKOSC_GRUPY.
Gdy inny programista będzie czytać twój kod, to nie będzie musiał zgadywać, co
oznacza liczba 50. Natomiast, za każdym razem, gdy zobaczy nazwę WIELKOSC_GRUPY,
będzie wiedział, że zawiera ona liczbę studentów w grupie. Analogicznie, przy
użyciu makr możesz w programie zastępować złożone równania, takie jak
wynik = (x*y-3)*(x*y-3)*(x*y-3);

nazwą makra SZESCIAN. Przypomina to wywołanie funkcji:
W tym przykładzie makro nie tylko poprawia czytelność kodu programu, ale
upraszcza również instrukcję zmniejszając możliwość błędu. Podczas tej lekcji
przedstawimy szczegółowo stałe i makra. Pod koniec tej lekcji będziesz rozumiał
następujące zagadnienia podstawowe:
Aby programy były bardziej czytelne, programiści często zastępują wartości
liczbowe znaczącymi nazwami stałych.
Dzięki używaniu w całym programie nazw stałych zamiast wartości liczbowych
program będzie łatwiejszy do modyfikacji.
Możesz w programach w C++ zastępować równania znaczącymi nazwami makr.
Kompilator C++ przed skompilowaniem programu wywołuje specjalny program zwany
preprocesorem, który zastępuje nazwy stałych i makr w programie odpowiednią
wartością.
Makra są wykonywane szybciej niż funkcje, ale zwiększają rozmiar programu
wykonywalnego.
Większość kompilatorów C++ zawiera predefiniowane stałe lub makra, które
możesz wykorzystywać w programie.


Używanie nazw stałych
Nazwa stałej to po prostu nazwa, do której przypisujesz stałą wartość, która w
przeciwieństwie do wartości zmiennej nie może się zmieniać w trakcie wykonywania
programu. Definiujesz stałe przy użyciu dyrektywy preprocesora (specjalnej
instrukcji dla preprocesora kompilatora) #define. Na przykład następująca
instrukcja definiuje stałą WIELKOSC_GRUPY o wartości 50:
#define WIELKOSC_GRUPY 50

Aby rozróżniać stałe od zmiennych, większość programistów stosuje do nazw
stałych duże litery. Przedstawiony poniżej program STALA.CPP definiuje i
wyświetla stałą WIELKOSC_GRUPY:
#include

#define WIELKOSC_GRUPY 50 // Liczba studentów w grupie

void main(void)
{
cout << "Stała WIELKOSC_GRUPY wynosi " << WIELKOSC_GRUPY << endl;
}

Jak widzimy, ten program definiuje stałą przy użyciu dyrektywy #define na
początku kodu źródłowego. Po zdefiniowaniu stałej możesz korzystać z jej
wartości w całym programie po prostu podając jej nazwę.
Uwaga: Przedstawiona definicja stałej nie jest zakończona średnikiem. Gdybyś na
końcu definicji umieścił średnik, to preprocesor włączałby średnik do definicji.
Na przykład, jeśli wstawisz średnik za liczbą 50 w dyrektywie #define
przedstawionego programu, to preprocesor zastąpi każde wystąpienie stałej
WIELKOSC_GRUPY wartością 50 i średnikiem, co prawdopodobnie spowoduje błąd
syntaktyczny.
Znaczenie dyrektyw preprocesora
Kompilator przed skompilowaniem twojego programu wywołuje specjalny program
noszący nazwę preprocesora. Preprocesor wyszukuje w twoim programie linie
zaczynające się od znaku #, np. #include lub #define. Jeśli na przykład
preprocesor napotka dyrektywę #include, to włączy w tym miejscu twojego pliku
źródłowego podany plik, tak jak gdybyś przy tworzeniu programu wpisał jego
zawartość. Wszystkie programy przedstawione w tej książce przy użyciu dyrektywy
#include instruowały preprocesor, by włączył zawartość pliku nagłówkowego
iostream.h do twojego pliku źródłowego. Jeśli preprocesor napotka dyrektywę
#define, to utworzy podaną stałą lub makro. Później, gdy preprocesor napotka
nazwę tej stałej lub makra, to zastąpi ją wartością określoną dyrektywą #define.
Gdy definiujesz stałe w swoich programach, to C++ nie ogranicza zakresu
stosowania stałych do wartości liczbowych. Możesz także przy ich użyciu
przechowywać teksty i liczby zmiennoprzecinkowe. Na przykład, następujący
program INFOKSIA.CPP korzystając z dyrektywy #define tworzy trzy stałe
zawierające informacje o tej książce:
#include

#define TYTUL "Wygraj z C++"
#define LEKCJA 27
#define CENA 22.95

void main(void)
{
cout << "Tytuł książki: " << TYTUL << endl;
cout << "Bieżąca lekcja: " << LEKCJA << endl;
cout << "Cena: " << CENA << " zł." << endl;
}

Gdy skompilujesz i uruchomisz ten program, to otrzymasz na ekranie następujące
wyjście:
C:\> INFOKSI
Tytuł książki: Wygraj z C++
Bieżąca lekcja: 37
Cena: 22.95 zł.

Tworzenie stałych przy użyciu dyrektywy #define
Dla poprawy czytelności programu powinieneś w całym kodzie źródłowym zastąpić
wartości liczbowe znaczącymi nazwami stałych. Do definiowania stałych w
programie służy dyrektywa preprocesora #define. Powinieneś umieszczać definicje
stałych na początku pliku źródłowego. Ponadto, aby rozróżnić nazwy zmiennych i
nazwy stałych, większość programistów używa do nazw stałych dużych liter. Na
przykład, następująca dyrektywa #define tworzy stałą o nazwie SEKUND_W_GODZINIE:
#define SEKUND_W_GODZINIE 3600
Po wywołaniu kompilatora dla programu preprocesor C++ zastąpi każde użycie nazwy
SEKUND_W_GODZINIE wartością liczbową 3600. Zwróć uwagę na to, że definicja
stałej nie jest zakończona średnikiem. Gdybyś dołączył średnik za liczbą 3600,
to preprocesor zastępowałby wystąpienia nazwy SEKUND_W_GODZINIE tą liczbą i
średnikiem (3600;) prawdopodobnie powodując błąd syntaktyczny.


Użycie stałych upraszcza modyfikacje kodu
Oprócz poprawy czytelności programów, dzięki użyciu stałych twoje programy są
łatwiejsze do modyfikacji. Na przykład, następujący fragment kodu zawiera wiele
odwołań do liczby 50 (liczby studentów w grupie):
#include

void main(void)
{
int wyniki_egzaminu[50];
char stopnie[50];

int student;

for (student = 0; student < 50; student++)
wczytaj_wyniki_egzaminu (student);

for (student = 0; student < 50; student++)
oblicz_stopien (student);

for (student = 0; student < 50; student++)
drukuj_stopien (student);
}

Załóżmy, na przykład, że liczba studentów w grupie wzrasta do 55. W takim
wypadku musisz wrócić do edycji programu i zastąpić każde odwołanie do liczby 50
wartością 55. Inne rozwiązanie polega na użyciu w programie stałej
WIELKOSC_GRUPY:
#include

#define WIELKOSC_GRUPY 50

void main(void)
{
int wyniki_egzaminu[WIELKOSC_GRUPY];
char stopnie[WIELKOSC_GRUPY];

int student;

for (student = 0; student < WIELKOSC_GRUPY; student++)
wczytaj_wyniki_egzaminu (student);

for (student = 0; student < WIELKOSC_GRUPY; student++)
oblicz_stopien (student);

for (student = 0; student < WIELKOSC_GRUPY; student++)
drukuj_stopien (student);
}

W tym programie, aby zmienić w całym kodzie wielkość grupy, wystarczy tylko
zmodyfikować linię zawierającą dyrektywę #define, która definiuje stałą:
#define WIELKOSC_GRUPY 55



Zastępowanie równań makrami
W programach realizujących operacje ze świata rzeczywistego używa się często
złożonych wyrażeń, np.:
wynik = (x*y-3)*(x*y-3)*(x*y-3);

W tym przykładzie program oblicza wartość (x*y-3) do potęgi trzeciej, czyli do
sześcianu. Aby poprawić czytelność programu i zmniejszyć prawdopodobieństwo
pomyłki przy wpisywaniu wyrażenia, możesz utworzyć makro pod nazwą SZESCIAN,
którego będziesz używać w programie w następujący sposób.
wynik = SZESCIAN(x*y-3);

I znowu programiści przyjęli zwyczaj używania dużych liter w nazwach makr, aby
odróżniały się od nazw funkcji.
Do tworzenia makr służy dyrektywa preprocesora #define. Na przykład, następująca
instrukcja tworzy makro SZESCIAN:
#define SZESCIAN (x) ((x) * (x) * (x))

Jak widzimy, makro trzykrotnie mnoży przez siebie wartość parametru x.
Przedstawiony poniżej program PISZSZES.CPP przy użyciu makra SZESCIAN wyświetla
sześciany liczb od l do 10:
#include

#define SZESCIAN (x) ((x) * (x) * (x))

void main(void)
{
for (int i = 1; i <= 10; i++)
cout << i << " do sześcianu wynosi " << SZESCIAN (i) << endl;
}

Podczas kompilacji tego programu preprocesor C++ zastąpi każde użycie makra
SZESCIAN odpowiednią definicją. Innymi słowy, po zastąpieniu nazwy makra
otrzymamy kod:
#include

#define SZESCIAN (x) ((x) * (x) * (x))

void main(void)
{
for (int i = 1; i <= 10; i++)
cout << i << " do sześcianu wynosi " << SZESCIAN (i) << endl;
}

#include

#define SZESCIAN (x) ((x) * (x) * (x))

void main(void)
{
for (int i = 1; i <= 10; i++)
cout << i << " do sześcianu wynosi " << ((x) * (x) * (x)) << endl;
}

Zwróć uwagę na to, że w definicji makra parametr x jest w nawiasach, czyli jest
((x) * (x) * (x)), a nie (x*x*x). Przy tworzeniu makr powinieneś umieszczać
parametry w nawiasach, tak jak w tym przykładzie, aby mieć pewność, że C++ w
poprawny sposób obliczy wartość wyrażenia. Jak być może pamiętasz z lekcji 5,
C++ określa kolejność wykonywania operacji arytmetycznych na podstawie
priorytetów operatorów. Załóżmy, na przykład, że program używa makra SZESCIAN
dla równania 3+5-2, czyli:
wynik = SZESCIAN (3+5-2);

Gdyby parametry makra były umieszczone w nawiasach, to preprocesor wygenerowałby
następującą instrukcję:
wynik = ((3+5-2) * (3+5-2) * (3+5-2));

Jeśli natomiast w definicji makra pominiesz nawiasy, to preprocesor wygeneruje
instrukcję:
wynik = (3+5-2 * 3+5-2 * 3+5-2);

Jeśli obliczysz oba równania, to zauważysz, że wyniki są różne. Umieszczając
argumenty makra w nawiasach możesz uniknąć takich błędów.


Czym makrn różnią się od funkcji
Definicja makra nie jest funkcją. Gdy twój program używa funkcji, to w programie
wykonywalnym jest tylko jedna kopia instrukcji funkcji. Przy każdym wywołaniu
funkcji program umieszcza parametry na stosie, a następnie skacze do kodu
funkcji. Po zakończeniu wykonywania funkcji parametry są zdejmowane ze stosu, a
program skacze do pierwszej instrukcji umieszczonej za wywołaniem funkcji.
Natomiast dla makra preprocesor zastępuje każde odwołanie do nazwy makra w
kodzie źródłowym definicją makra. Na przykład, gdyby przedstawiony program
używał nazwy makra SZESCIAN w 100 różnych miejscach, to preprocesor 100 razy
umieściłby kod z definicji makra. Gdy korzystasz z makr to nie ma przy wywołaniu
nakładów związanych z umieszczaniem parametrów na stosie i zdejmowaniem ich
stamtąd, ani kosztów wynikających ze skoku do kodu funkcji i powrotu. Jednak,
ponieważ preprocesor zastępuje każde odwołanie do makra odpowiednim kodem,
używanie makr zwiększa rozmiar programu wykonywalnego.


Elastyczność użycia makr
W swoich programach możesz używać makr w rozmaity sposób. Pamiętaj jednak, że
twoim celem jest uproszczenie kodowania i poprawa czytelności programu.
Przedstawiony poniżej program MAKPRZER.CPP ilustruje elastyczność użycia makr.
Ponadto ten program może dać Ci lepsze wyobrażenie o tym, w jaki sposób
preprocesor zastępuje nazwę makra odpowiednimi instrukcjami:
#include

#define przerwa (x) { \
cout << "Przerwa " << x << endl; \
for (long int i=0; i < x; i++)
; \
}

void main(void)
{
przerwa (100000L);

przerwa (200000L);

przerwa (300000L);
}

W tym przykładzie, ponieważ definicja makra zajmuje wiele linii, to na końcu
każdej linii, która jest kontynuowana w następnej, jest umieszczony znak '\'.
Gdy preprocesor napotka odwołanie do makra, to zastąpi je ciągiem instrukcji z
definicji makra.


Zapamiętaj
Celem użycia makr i stałych jest podniesienie czytelności programów i
uproszczenie programowania. Podczas tej lekcji dowiedziałeś się, w jaki sposób
tworzyć i wykorzystywać stałe i makra w kodzie programów. Podczas lekcji 38
będziesz się uczyć o polimorfiźmie, który umożliwia zmianę form obiektów podczas
działania programu. Zanim jednak przejdziemy do lekcji 38 upewnij się, że
opanowałeś już następujące zagadnienia podstawowe:
Makra i stałe poprawiają czytelność programów zastępując złożone równania i
liczby znaczącymi nazwami.
Zastępując w całym programie wartości liczbowe nazwami stałych zmniejszasz
liczbę modyfikacji, które byłoby trzeba wprowadzić, gdybyś później musiał
zmienić wartość liczby używanej w programie.
Podczas kompilacji wywoływany jest specjalny program zwany preprocesorem,
który zastępuje użyte w programie nazwy stałych i makr odpowiednimi
wartościami i kodem.
Makra działają szybciej niż funkcje, ale zwiększają rozmiar programu
wykonywalnego.
Jeśli definicja makra zajmuje więcej niż jedną linię, to możesz na końcu
każdej linii umieszczać znak '\', który informuje preprocesor, że definicja
jest kontynuowana w następnej linii.



WsteczSpis treściDalej



Wyszukiwarka

Podobne podstrony:
Kris Jamsa Wygraj Z C lekcja32
Kris Jamsa Wygraj Z C lekcja 5
Kris Jamsa Wygraj Z C lekcja23
Kris Jamsa Wygraj Z C lekcja38
Kris Jamsa Wygraj Z C lekcja35
Kris Jamsa Wygraj Z C lekcja20
Kris Jamsa Wygraj Z C lekcja27
Kris Jamsa Wygraj Z C lekcja34
Kris Jamsa Wygraj Z C lekcja18
Kris Jamsa Wygraj Z C lekcja17
Kris Jamsa Wygraj Z C lekcja25
Kris Jamsa Wygraj Z C lekcja14
Kris Jamsa Wygraj Z C lekcja 4
Kris Jamsa Wygraj Z C lekcja33
Kris Jamsa Wygraj Z C lekcja 7
Kris Jamsa Wygraj Z C lekcja30
Kris Jamsa Wygraj Z C lekcja12
Kris Jamsa Wygraj Z C lekcja28
Kris Jamsa Wygraj Z C lekcja 6

więcej podobnych podstron