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.