Instrukcja skoku: Różnice pomiędzy wersjami

Dodane 228 bajtów ,  13 lat temu
m
drobne redakcyjne
[wersja przejrzana][wersja przejrzana]
Usunięta treść Dodana treść
Konradek (dyskusja | edycje)
Nie podano opisu zmian
Konradek (dyskusja | edycje)
m drobne redakcyjne
Linia 1:
'''Instrukcja skoku''' – instrukcja w językach programowania, która powoduje bezwarunkowe przekazanie sterowania w inne miejsce, (tzw. ''skok)''. Występuje w tak odległych od siebie językach, jak [[Fortran]], [[Algol (język programowania)|Algol]], [[COBOL]], [[SNOBOL]], [[Basic]], [[C (język programowania)|C]]/[[C++]], [[Perl]], [[Pascal (język programowania)|Pascal]], [[PHP]]<ref>Od wersji 5.3 [http://php.net/manual/en/control-structures.goto.php]</ref> i wielu innych. Miejsce skoku identyfikuje się za pomocą numeru wiersza programu (zwykle w [[język interpretowany|językach interpretowanych]]) bądź [[etykieta (informatyka)|etykiety]] (najczęściej w [[język kompilowany|językach kompilowanych]]).
 
== Przykład ==
Instrukcja skoku jest instrukcją [[paradygmat programowania|paradygmatu]] [[programowanie imperatywne|imperatywnego]], stosowanego przede wszystkim do nauki [[programowanie|programowania]] (np. języki [[BASIC]], [[LOGO]]) oraz w programowaniu niskopoziomowym (np. języki [[asembler|asemblera]] i [[C]]). Paradygmat [[programowanie proceduralne|proceduralny]] odchodził od instrukcji skoku na rzecz [[podprogram|procedur (funkcji)]], jednak całkowite odejście od nich bywa nieopłacalne. Pierwszym paradygmatem, którego celem było ograniczenie stosowania skoków (poprzez zastąpienie sterowaniem przepływu kodu [[instrukcja warunkowa|instrukcji porównania]] i skoku poprzez [[instrukcja warunkowa|instrukcje warunkowe]] i [[instrukcja wyboru]]) był paradygmat [[programowanie strukturalne|strukturalny]].
Niżej przedstawiono kod w [[Perl]]u: instrukcją skoku jest <code>goto</code>, po której następuje identyfikator etykiety (w kodzie etykieta zawiera ma sobie dwukropek). Wynikiem działania poniższego programu jest wyświetlenie napisu „Ala ma kota”.
 
<source lang="perl">
Istnieją paradygmaty, jak np. [[programowanie obiektowe|obiektowy]], [[programowanie funkcyjne|funkcyjny]], czy [[programowanie sterowane zdarzeniami|zdarzeniowy]], w których instrukcja ta nie istnieje. Mimo wszystko wiele języków realizujących kilka paradygmatów (przede wszystkim opartych na [[C]]) zawiera tę instrukcję. Nie zaleca się mieszania paradygmatów ze względu na możliwość zaciemnienia jego struktury, częstym przykładem jest właśnie zastosowanie imperatywnej instrukcji skoku kodzie obiektowym (zwłaszcza, gdy skok odbywa się między dwoma nie związanymi ze sobą blokami kodu, np. z ciała jednej [[Klasa (programowanie)|klasy]] do drugiej). Umiejętnie zastosowana instrukcja skoku może jednak znacząco ułatwić opuszczenie imperatywnej bądź proceduralnej części obiektowego kodu (np. wielokrotnie zagnieżdżone instrukcje warunkowe lub wyboru).
 
Miejsce skoku identyfikuje się za pomocą numeru wiersza programu (zwykle w [[język interpretowany|językach interpretowanych]]) bądź [[etykieta (informatyka)|etykiety]] (najczęściej w [[język kompilowany|językach kompilowanych]]).
 
== Przykłady ==
Kodzie w [[Perl]]u:
<pre>
goto C;
A:
Linia 21 ⟶ 15:
goto B;
D:
</presource>
 
== Przepływ kontroli ==
Wynikiem działania powyższego programu jest wydrukowanie napisu "Ala ma kota".
Do zaprogramowania każdego diagramu przepływu czy każdego [[automat o skończonej liczbie stanów|automatu o skończonej liczbie stanów]] bez duplikacji kodu, a więc do sterowania przepływem kontroli w kodzie, którego żadna część się nie powtarza, wystarczą instrukcje skoku warunkowego (poprzedzone instrukcją porównania) i bezwarunkowego.
 
Obserwacja ta znalazła zastosowanie w konstrukcji [[procesor]]ów i wyrażenia tego w języku [[asembler]]a, gdzie dostępne są te właśnie instrukcje (instrukcje skoku bezwarunkowego <code>JMP</code> i warunkowego <code>Jxx</code> w architekturze [[x86]], gdzie <code>xx</code> symbolizują stan [[flaga (informatyka)|flag]] [[rejestr stanu|rejestru stanu]] zmienianego po części instrukcji procesora).
== Jak można sterować przepływem kontroli ==
Aby sterować przepływem kontroli w programie w sposób, który umożliwia zaprogramowanie każdego diagramu przepływu czy każdego [[automat o skończonej liczbie stanów|automatu o skończonej liczbie stanów]] bez duplikacji kodu wystarczy jedna instrukcja <tt>if (warunek) { goto X; }</tt>, ze szczególnym przypadkiem <tt>if (prawda) { goto X; }</tt>. Tak jest to rozwiązane na poziomie [[asembler]]a - dostępne są jedynie instrukcje skoku bezwarunkowego (<tt>JMP</tt> na [[x86]]) i warunkowego (na [[x86]] <tt>JZ</tt>, <tt>JNZ</tt>, <tt>JG</tt>, <tt>JC</tt> itd, gdzie literki po <tt>J</tt> oznaczają stan flag oznaczających wynik ostatniej operacji).
 
Pierwsze języki, przede wszystkim ze względu na nacisk na łatwość konstrukcji [[kompilator]]ów nie odbiegały znacząco zasobem instrukcji od asemblera, np. w pierwszych wersjach [[Fortran]]a jedyną instrukcją warunkową był właśnie skok – nie można było warunkowo przypisać wartości czy wykonać grupy poleceń. Z czasem do języków zaczęto dodawać inne instrukcje kontroli przepływu: wykonania warunkowego (<code>if (''warunek'') { ''polecenie1'' } else { ''polecenie2'' }</tt>, różne rodzaje [[pętla (informatyka)|pętli]] (<code>while</code>, <code>for</code>), rekurencyjność, instrukcje ponowienia (<code>redo</code>), [[instrukcja kontynuacji|następnej iteracji]] (<code>next</code> lub <code>continue</code>) lub [[instrukcja opuszczenia|zakończenia wykonywania]] (<code>last</code> lub <code>break</code>) pętli,
W [[Fortran]]ie pierwotnie jedyną instrukcją warunkową był właśnie skok - nie można było warunkowo przypisać wartości czy wykonać grupy poleceń. Było to z jednej strony całkowicie wystarczające, z drugiej zaś mało ekspresywne.
te same instrukcje z wielopoziomowymi pętlami (<code>X: foreach $a(@A) { foreach $b(@B) { ...; if (...) { last X; }} }</code>), [[wyjątek|wyjątki]], [[iterator]]y, [[funkcja wyższego rzędu|funkcje wyższego rzędu]], [[wątek (informatyka)|wątki]] itd., co uczyniło z instrukcji skoku instrukcję na wskroś przestarzałą.
 
== Paradygmaty programowania ==
Z czasem dodawano nowe instrukcje kontroli przepływu: wykonania warunkowego (<tt>if (warunek) { POLECENIE1 } else { POLECENIE2 }</tt>, kilku typów pętli (<tt>while</tt>, <tt>for</tt>), funkcje rekurencyjne, instrukcje ponowienia (<tt>redo</tt>), [[Instrukcja kontynuacji|następnej iteracji]] (<tt>next</tt> lub <tt>continue</tt>) lub [[Instrukcja opuszczenia|zakończenia wykonywania]] (<tt>last</tt> lub <tt>break</tt>) pętli,
{{seealso|paradygmat programowania}}
te same instrukcje z wielopoziomowymi pętlami (<code>X: foreach $a(@A) { foreach $b(@B) { ...; if (...) { last X; }} }</code>), [[wyjątek|wyjątki]], [[iterator]]y, [[funkcja wyższego rzędu|funkcje wyższego rzędu]], [[wątek (informatyka)|wątki]] itd.
Instrukcja skoku jest instrukcją [[paradygmatprogramowanie programowaniaimperatywne|paradygmatu]] [[programowanie imperatywne|imperatywnego]], stosowanego przede wszystkim do nauki [[programowanie|programowania]] (np. języki [[BASIC]], [[LOGO]]) oraz w programowaniu niskopoziomowym (np. języki [[asembler|asemblera]] i [[C]]). Paradygmat [[programowanie proceduralne|Paradygmat proceduralny]] odchodził od instrukcji skoku na rzecz [[podprogram|procedur (funkcji)]], jednak całkowite odejście od nich bywa nieopłacalne. Pierwszym paradygmatem, którego celem było ograniczenie stosowania skoków (poprzez zastąpienie sterowaniem przepływu kodu [[instrukcja warunkowa|instrukcji porównania]] i skoku poprzez [[instrukcja warunkowa|instrukcje warunkowe]] i [[instrukcja wyboru]]) był paradygmat [[programowanie strukturalne|paradygmat strukturalny]].
 
Istnieją paradygmaty, jak np. [[programowanie obiektowe|obiektowy]], [[programowanie funkcyjne|funkcyjny]], czy [[programowanie sterowane zdarzeniami|zdarzeniowy]], w których instrukcja ta nie istnieje. Mimo wszystko wiele języków realizujących kilka paradygmatów (przede wszystkim opartych na [[C (język programowania)|C]]) zawiera tę instrukcję. Nie zaleca się mieszania paradygmatów ze względu na możliwość zaciemnienia jego struktury, częstym przykładem jest właśnie zastosowanie imperatywnej instrukcji skoku kodzie obiektowym (zwłaszcza, gdy skok odbywa się między dwoma nie związanymi ze sobą blokami kodu, np. z ciała jednej [[Klasa (programowanie)|klasy]] do drugiej). Umiejętnie zastosowana instrukcja skoku może jednak znacząco ułatwić opuszczenie imperatywnej bądź proceduralnej części obiektowego kodu (np. wielokrotnie zagnieżdżone instrukcje warunkowe lub wyboru).
Są one dużo bardziej ekspresywne od <tt>goto</tt>, którego programiści piszący w wysokopoziomowych językach programowania powinni unikać. Jednak czasami takiej możliwości nie mają piszący w językach z relatywnie ubogimi strukturami kontroli przepływu, takimi jak [[C (język programowania)|C]] czy [[Basic]].
 
== Zobacz też ==
12 936

edycji