Przeciązanie goto?

0

Troche głupie pytanie ale czy da się i jak to zrobić by z kilku miejsc móc skoczyć w jedno miejsce ale aby nie pisać zbyt dużo kodu:

#include<iostream>
using namespace std;
void fun_1()
{
     cout<<"a"<<endl;
     goto a:
}
void fun_2()
{
     cout<<"b"<<endl;
     goto a:
}
int main()
{
   a:
   fun_1();
   fun_2();
}
 
0

kod używający goto to raczej zły kod, do tego masz pętle, funkcje, ify, switche, break, continue, wyjątki, i nie wiem co jeszcze

edit;

niektóre z tych opcji prawdopodobnie "przeciążają goto" hah

0

Dla mnie łatwiej jest użyć goto ale jeśli należy unikać to spróbuje inaczej XD

0

Goto to zło wcielone, nie staraj sie unikać, ale nie używaj go w ogóle.
Nie wiem czy istnieją rzeczy które można zrobić tylko za pomocą instrukcji goto (pewnie istnieją, niech ktoś sie wypowie).

0

A co jest złego w goto?

0
aksjio napisał(a):

A co jest złego w goto?

Głównie to że robi niezły syf w kodzie. Powinni dawno tego zakazać. No ewentualnie w Asemblerze mi się czasem przydawało:D

0

setjmp i longjmp, ale niech to wszyscy potraktują jako ciekawostkę :).

Lepiej przemyśl architekturę swojego programu i control-flow zrealizuj za pomocą funkcji.

0

Nie wiem czy istnieją rzeczy które można zrobić tylko za pomocą instrukcji goto (pewnie istnieją, niech ktoś sie wypowie).

Nie ma. Potrzebne jest jedno z trzech: rekurencja, goto albo while by język programowania był kompletny w sensie Turinga.
C++ ma wszystkie trzy mechanizmy; dowolne dwa można wyrzucić i nadal można napisać wszystko co można było napisać mając trzy.

2

W Twoim przypadku, nawet jeśli udało by Ci się napisać ten kod tak jak chciałeś to fun_2 nigdy by się nie wywołało, bo po skonczeniu fun_1 znowu wywolbys fun_1.
Prawdopodobnie chodzi Ci o coś takiego:

#include<iostream>
using namespace std;
void fun_1()
{
     cout<<"a"<<endl;
}
void fun_2()
{
     cout<<"b"<<endl;
}
int main()
{
   while (true)
   {
     fun_1();
     fun_2();
   }
}

Ja osobiście nie lubię goto ze względu na to, że czytanie takiego kodu to jest potem katorga. Nazwa funkcji powinna mówić co ona robi i nie powinna robić nic więcej, a jeśli zaczniesz skakać w losowe miejsca to ciężko będzie jakąkolwiek nazwe dla Twojej funkcji wymyślić.

co do goto, patrz na ten przykład (zakładając, że skompilowałby się):

#include<iostream>
using namespace std;
void fun_1()
{
     goto a; // pomijasz instrukcje "ret"
} // instrukcja "ret": sciagasz zapamietana wartosc ze stosu i skaczesz do niej

void fun_2()
{
    fun_1(); // (3) wkladasz na stos miejsce wywolania i skaczesz do fun_1
}

int main()
{
   fun_1(); // (1) w momencie wywolania na stos wkladany jest adres miejsca wywolania i skok do fun_1
   a:
   fun_2(); // (2) tutaj to samo
}

patrzac na ten kod, w teorii powinienes wywolac raz fun_1, po czym w nieskonczonosc fun_2
przeanalizujmy co sie stanie krok po kroku w praktyce:
wywolujesz fun_1, na stosie masz: adres (1),
fun_1 konczy sie, wchodzisz do a, wywolujesz fun_2, na stosie masz: adres (1), adres (2)
fun_2 wywoluje fun_1, na stosie masz: adres (1), adres (2), adres (3)
wracasz do a, znowu wywolujesz fun_2 i znowu na stos dochodza nowe wartosci i nigdy nie sa sciagane, po chwili dostajesz stack overflow

Zauwaz ze zeby kompilator byl w stanie to zrealizowac to musialby znac kontekst (miejsce) wywolania fun_1. w tym przypadku dzieje sie to tylkow main i fun_2, zalozmy ze dodasz jakies komplikowane skoki. Kompilator nie jest w stanie sledzic skad to wywolujesz, to nie ma prawa dzialac (chyba ze kompilator zaczalby bez Twojej wiedzy dodawac logike sledzaca w kodzie, a tego nie chcesz, ale wydaje mi sie ze mimo wszystko znalazlbys przypadek taki, zeby zupelnie zgubic kontekst wywolania i kompilator by nie wiedzial zupelnie co zrobic z Twoim kodem, patrz na przyklad ponizej).

void fun1()
{
  a:
  goto b;
}

void fun2()
{
  b:
  goto a;
}
int main()
{
  fun1();
}

W tym momencie zupelnie wychodzisz z maina i juz do niego nie wrocisz. Jak jeszcze dodasz kilka instrukcji warunkowych to wszystko sie posypie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1