Kris Jamsa Wygraj Z C++ lekcja34


Lekcja 35LEKCJA 35
Funkcje inline i wstawianie kodu w assemblerze
Programy, które utworzyliśmy od lekcji 8, szeroko wykorzystywały funkcje. Jak
już wiesz, jedyną wadą funkcji jest fakt, iż z ich wywoływaniem jest związany
nakład (zwiększenie czasu wykonywania programu) wynikający z konieczności
umieszczania przy każdym wywołaniu parametrów na stosie. Jak dowiesz się podczas
tej lekcji, dla krótkich funkcji możesz wykorzystywać technikę zwaną kod inline,
która umieszcza instrukcje funkcji w miejscu każdego wywołania funkcji w całym
programie, dzięki czemu można wyeliminować nakład czasowy związany z
wywoływaniem funkcji. Jeśli będziesz używać funkcji inline, to twoje programy
będą działać nieco szybciej. Pod koniec tej lekcji będziesz rozumiał następujące
zagadnienia podstawowe:
Aby poprawić szybkość działania programów eliminując koszty związane z
wywoływaniem funkcji, możesz nakazać kompilatorowi C++, aby w miejscu wywołań
funkcji umieszczał jej kod (inline), analogicznie do rozwijania makra.
Dzięki funkcjom inline programy pozostają czytelne (osoba czytająca kod widzi
wywołanie funkcji), ale eliminowany jest nakład związany z wkładaniem
parametrów na stos i pobieraniem ich stamtąd oraz ze skokiem do funkcji i
powrotem z niej.
W niektórych programach będziesz musiał wstawiać kod w assemblerze realizujący
określone zadanie.
Aby uprościć programowanie w assemblerze możesz w języku C++ umieszczać w
programach funkcje assemblerowe inline.


Znaczenie funkcji inline
Gdy definiujesz funkcję w programie, to kompilator języka C++ przekształca
(tłumaczy) kod funkcji na język maszyny przechowując w programie tylko jedną
kopię instrukcji funkcji. Przy każdym wywołaniu funkcji w programie kompilator
C++ generuje specjalne instrukcje, które umieszczają na stosie parametry
wywołania, a następnie kieruje sterowanie programu do instrukcji funkcji. Po
zakończeniu funkcji parametry są zdejmowane ze stosu, a wykonywanie programu
jest kontynuowane począwszy od pierwszej instrukcji znajdującej się za
wywołaniem funkcji. Wkładanie i zdejmowanie argumentów ze stosu oraz kierowanie
sterowania do funkcji i z powrotem powoduje dodatkowy nakład, który sprawia, że
program jest wykonywany nieco wolniej niż gdyby w miejscu każdego wywołania
funkcji był umieszczony jej kod. Na przykład weźmy następujący program
WYWSYGN.CPP, który wywołuje funkcję pisz_komunikat emitującą z głośnika
komputera określoną liczbę sygnałów i wyświetlającą podany komunikat:
#include

void pisz_komunikat (int licznik, char *komunikat)
{
int i;

for (i = 0; i < licznik; i++)
cout << '\a';

cout << komunikat << endl;
}

void main(void)
{
pisz_komunikat (3, "Wygraj z C++");
pisz_komunikat (2, "Lekcja 35");
}

Przedstawiony poniżej program BEZWYW.CPP nie wywołuje funkcji pisz_komunikat,
ale w miejscu wywołań funkcji ma wstawione ich instrukcje:
#include

void main(void)
{
int i;

for (i = 0; i < 3; i++)
cout << '\a';

cout << "Wygraj z C++" << endl;

for (i = 0; i < 2; i++)
cout << '\a';

cout << "Lekcja 35" << endl;
}

Oba programy robią dokładnie to samo. Ponieważ program BEZWYW nie wywołuje
funkcji pisz_komunikat, wykonuje się nieco szybciej niż WYWSYGN. Dla tych
programów różnica czasów działania jest niezauważalna, jeśli jednak funkcja
byłaby wywoływana 1000 razy, to mógłbyś zaobserwować niewielką zmianę szybkości
działania. Natomiast program BEZWYW jest mniej zrozumiały i mniej czytelny niż
jego odpowiednik zawierający wywołania funkcji.
Tworząc programy musisz się zawsze starać określić, kiedy powinieneś używać
funkcji, a kiedy wstawiać kod funkcji inline. Dla prostych programów wywoływanie
funkcji jest zwykle lepszym rozwiązaniem. Jeśli jednak piszesz program, w którym
zasadnicze znaczenie ma szybkość działania, to być może będziesz chciał
ograniczyć liczbę wywołań funkcji, jakie musi obsłużyć program.
Jednym sposobem ograniczania nakładów związanych z wywoływaniem funkcji jest
wstawianie w całym programie instrukcji funkcji, tak jak to zrobiliśmy w
programie BEZWYW. Jak jednak zauważyłeś, wyeliminowanie wywołań tylko jednej
funkcji znacznie "zabałaganiło" kod programu. Na szczęście C++ daje Ci do
dyspozycji słowo kluczowe inline, dzięki któremu możesz mieć korzyści płynące z
obu metod.


Używanie słowa kluczowego inline
Deklarując funkcję w programie możesz poprzedzić jej nazwę słowem kluczowym
inline. Gdy kompilator C++ je napotka, to przy tworzeniu pliku wykonywalnego w
języku maszyny będzie zastępować każde wywołanie funkcji jej instrukcjami. W ten
sposób możesz poprawiać czytelność programów dzięki używaniu funkcji podnosząc
jednocześnie szybkość ich działania dzięki wyeliminowaniu nakładów związanych z
wywoływaniem funkcji. Przedstawiony poniżej program INLINE.CPP definiuje funkcje
min i max jako inline:
#include

inline int max(int a, int b)
{
if (a > b)
return (a);
else
return (b)
}

inline int min(int a, int b)
{
if (a < b)
return (a);
else
return (b)
}

void main(void)
{
cout << "Minimum z 1001 i 2002 wynosi " << min(1001, 2002) << endl;
cout << "Maximum z 1001 i 2002 wynosi " << max(1001, 2002) << endl;
}

Dla tego programu kompilator C++ zastąpi każde wywołanie obu funkcji
odpowiednimi instrukcjami. Poprawiona została szybkość działania programu bez
pogarszania jego czytelności.
Znaczenie funkcji inline
Gdy kompilator C++ napotka słowo kluczowe inline przed definicją funkcji, to
będzie zastępować wywołania tej funkcji instrukcjami równoważnymi instrukcjom
wykonywanym przez funkcję. W ten sposób programy mogą poprawiać szybkość
działania, a jednocześnie są czytelne, bo w kodzie źródłowym są wywołania
funkcji.


Funkcje inline i klasy
Jak już wiesz, gdy definiujesz klasę, to definiujesz jej funkcje (metody)
wewnątrz klasy lub poza nią. Na przykład, następująca klasa pracownik zawiera
definicje swoich funkcji:
class pracownik {
public:
pracownik (char *imie_nazwisko, char *stanowisko, float zarobki)
{
strcpy (pracownik::imie_nazwisko, imie_nazwisko);
strcpy (pracownik::stanowisko, stanowisko);
pracownik::zarobki = zarobki;
}
void inf_o_prac (void)
{
cout << "Imię i nazwisko: " << imie_nazwisko << endl;
cout << "Stanowisko: " << stanowisko << endl;
cout << "Zarobki: " << zarobki << "zł." << endl;
}
private:
char imie_nazwisko[64];
char stanowisko[64];
float zarobki;
};

Takie umieszczanie kodu funkcji wewnątrz klasy odpowiada funkcjom inline. Gdy
utworzysz w ten sposób funkcje w klasie, to C++ będzie powtarzać kod funkcji dla
każdego utworzonego obiektu klasy umieszczając kod inline w miejscu każdego
wywołania metody. Zaletą takiego definiowania funkcji jest poprawa szybkości
działania programu. Wadą jest to, że programy mogą bardzo szybko stać się bardzo
duże w zależności od tego, w jaki sposób używasz obiektów. Poza tym włączanie
kodu funkcji do definicji klasy zmniejsza jej czytelność, co sprawia, że trudno
zrozumieć znaczenie składowych klasy.
Aby poprawić czytelność definicji klasy, możesz umieścić definicje jej funkcji
na zewnątrz definicji klasy, tak jak zwykle i poprzedzić nazwy funkcji słowem
kluczowym inline. Na przykład następująca definicja klasy instruuje kompilator,
by użył instrukcji inline dla wywołań funkcji inf_o_prac:
inline void pracownik::inf_o_prac (void)
{
cout << "Imię i nazwisko: " << imie_nazwisko << endl;
cout << "Stanowisko: " << stanowisko << endl;
cout << "Zarobki: " << zarobki << "zł." << endl;
}



Używanie instrukcji w assemblerze
Jak wiesz z lekcji 1, programiści mogą tworzyć programy przy użyciu wielu
różnych języków programowania. Kompilator przekształca instrukcje napisane w
danym języku na kod maszyny (zera i jedynki) zrozumiały dla komputera. Każdy typ
komputera ma język pośredni noszący nazwę assemblera, który można zakwalifikować
pomiędzy językiem maszyny j językiem wysokiego poziomu, takim jak C++.
Assembler przy użyciu różnych symboli reprezentuje instrukcje języka maszyny. W
niektórych zaawansowanych programach może być konieczne wykonanie operacji
niskiego poziomu, które wymagają użycia instrukcji w assemblerze. W takich
sytuacjach możesz używać instrukcji asm języka C++, aby włączać do programu
instrukcje w assemblerze. Przedstawiony poniżej program UZYJASM.CPP przy użyciu
instrukcji asm wstawia instrukcje w assemblerze, które w środowisku MS-DOS
emitują dźwięk z głośnika komputera:
#include

void main(void)
{
cout << "Przed wydaniem dźwięku" << endl;

asm {
MOV AH,2
MOV DL,7
INT 21H
}

cout << "Zrobione!" << endl;
}

Jak widzimy, przy użyciu instrukcji asm można wstawiać do programu w C++
instrukcje w assemblerze.


Zapamiętaj
Funkcje inline poprawiają szybkość działania programu dzięki wyeliminowaniu
nakładu związanego z wywoływaniem funkcji. Podczas tej lekcji dowiedziałeś się,
w jaki sposób i kiedy używać funkcji inline w twoich programach. Ponadto
zobaczyłeś jak można wstawiać do programów instrukcje assemblera wykonujące
określone zadania. Podczas lekcji 36 nauczysz się, w jaki sposób programy mogą
mieć dostęp do parametrów linii poleceń podanych przez użytkownika. Zanim jednak
przejdziemy do lekcji 36 upewnij się, że opanowałeś już następujące zagadnienia
podstawowe:
Umieszczanie parametrów na stosie i zdejmowanie ich oraz przechodzenie do kodu
funkcji i z powrotem wprowadza nakład, który powoduje wolniejsze działanie
programów.
Słowo kluczowe inline instruuje kompilator C++, by zastępował każde wywołanie
funkcji instrukcjami wykonywanymi przez tę funkcję. Ponieważ funkcje inline
pozwalają wyeliminować nakład związany z wywoływaniem funkcji, program działa
szybciej.
Gdy definiujesz funkcje wewnątrz klasy, to każdy tworzony w programie obiekt
korzysta z własnych instrukcji funkcji inline.
Słowo kluczowe asm pozwala włączać do programów w C++ instrukcje w
assemblerze.



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 lekcja18
Kris Jamsa Wygraj Z C lekcja17
Kris Jamsa Wygraj Z C lekcja25
Kris Jamsa Wygraj Z C lekcja14
Kris Jamsa Wygraj Z C lekcja36
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