plik


11.3 Wywołanie funkcji Dalej: 11.4 Argumenty domyślne W górę: 11. Funkcje Wstecz: 11.2 Deklaracje i definicje funkcji 11.3 Wywołanie funkcji Wywołanie funkcji ma postać nazwy tej funkcji z podaną w nawiasach okrągłych listą oddzielonych przecinkami argumentów. Oczywiście liczba argumentów wywołania musi być dokładnie taka jak liczba parametrów w deklaracji i definicji funkcji. Nawet jeśli funkcja jest bezargumentowa, nawiasy musimy podać: w przeciwnym przypadku nazwa zostanie potraktowana nie jako wywołanie, ale jak nazwa zmiennej wskaźnikowej wskazującej funkcję (więcej o wskaźnikach funkcyjnych powiemy w osobnym podrozdziale na ich temat ). Rolę argumentów mogą pełnić dowolne wyrażenia, których wartość jest typu zgodnego z zadeklarowanym typem odpowiedniego parametru funkcji. Nie musi być to typ identyczny z typem parametru: wywołanie będzie prawidłowe, jeśli wartość argumentu można niejawnie przekształcić na wartość zadeklarowanego typu parametru (patrz podrozdział o konwersjach standardowych ). Jeśli przy takiej konwersji może być tracona informacja (czyli jest to konwersja zawężająca, a nie promocja), to zazwyczaj podczas kompilacji otrzymamy ostrzeżenia. Tym niemniej kod może skompilować się, gdyż (w przeciwieństwie do Javy) takie konwersje mogą być w C/C++ legalne. Jeśli funkcja zwraca rezultat, to ostatnią wykonywaną instrukcją musi być zawsze instrukcja return zwracająca wartość typu, jaki został zadeklarowany jako typ funkcji, albo typu, który może być niejawnie przekształcony do typu funkcji. Jeśli funkcja jest bezrezultatowa, to instrukcja return może (choć nie musi) w niej występować - jeśli występuje, to nie może zawierać żadnego wyrażenia, którego wartość miałaby być zwrócona (za wyjątkiem wywołania funkcji typu void). Dla funkcji bezrezultatowych domniemywa się instrukcję return tuż przed nawiasem kończącym definicję ciała tej funkcji. Proces wywoływania możemy sobie wyobrażać tak (szczegóły mogą zależeć od platformy i od kompilatora): Obliczne są wartości argumentów, po czym dokonywane są konwersje potrzebne do przekształcenia tych wartości w wartości typu odpowiedniego parametru funkcji (co, oczywiście, powinno być wykonalne - w przeciwnym razie program jest błędny). Tak uzyskane wartości kopiowane są na stos programu. Zauważmy, że jeśli argumentem była zmienna, to na stos kładziona jest kopia jej wartości (po ewentualnej konwersji - wartość kładziona na stosie musi już być dokładnie takiego typu jak zadeklarowany typ odpowiadającego temu argumentowi parametru funkcji). Tak więc funkcja nie uzyskuje dostępu do zmiennej, która pełniła rolę argumentu, a tylko do kopii jej wartości w momencie wywołania. Sterowanie przechodzi do funkcji: kopie wartości argumentów na stosie są utożsamiane ze zmiennymi lokalnymi odpowiadającymi poszczególnym parametrom funkcji. Zmienne lokalne (definiowane w funkcji) umieszczane są również na stosie. Wyjątek stanowią zmienne definiowane z modyfikatorem static. Takie zmienne tworzone są raz: podczas pierwszego wywołania. Przy kolejnych wywołaniach funkcja ma dostęp do tej samej zmiennej statycznej. Istnieje ona aż do zakończenia programu. Różni się od zmiennej globalnej tym, że jej zasięgiem jest zasięg funkcji (od miejsca deklaracji do końca funkcji). Po zakończeniu wykonywania funkcji część stosu ze zmiennymi lokalnymi (również tymi odpowiadającymi parametrom funkcji), jest usuwana, tak aby stan stosu odpowiadał temu sprzed wywołania (zwijanie stosu). Jeśli funkcja jest rezultatowa, to wynik jest zwracany do funkcji wywołującej (możemy sobie wyobrażać, że również poprzez stos, choć w praktyce stosuje się inne mechanizmy). Rozpatrzmy przykład ilustrujący konwersje argumentów i rezultatu funkcji:

Wyszukiwarka

Podobne podstrony:
node66 CE3G6OHPTG3WTM5STOUZXAZ7YOZVMBIG4CHFEHQ
node66
node66 N4LFIQ2YJ6Q6XEEUZ4XPOTSWIV66QFOGBXPDD7A
node66
node66 RLQU72ZR4D6LRKFRM2BT5WANQGGJGIW56PIEDHA
node66
node66

więcej podobnych podstron