Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: novomente 18. 08. 2019, 09:57:48

Název: Použití příkazu GOTO v jazyku C
Přispěvatel: novomente 18. 08. 2019, 09:57:48
Zdravím,

použil jste někdy někdo příkaz "goto" v jazyku C v programátorské praxi?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: JmJ 18. 08. 2019, 10:15:44
Ano. I v C++ i v C#.

Kazdopadne rozhodne nejde o beznou vec, ale jsou urcite situace, kde se to hodi. Odhaduju to tak na jeden blok kodu rizeny pres GOTO za 5 let ;-)
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: aaa158 18. 08. 2019, 11:39:59
mnohokrat  ;)

Tiez pozri na https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/

https://www.google.com/search?q=number+of+gotos+in+linux+kernel

 atd.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Dráb 18. 08. 2019, 21:44:49
Citace
použil jste někdy někdo příkaz "goto" v jazyku C v programátorské praxi?
Záleží na stylu programování. Někdy to téměř vyžaduje.
Kód: [Vybrat]
err = a_init();
if (err)
  goto Exit;

err = b_init();
if (err)
  goto a;

err = c_init();
if (err)
  goto b;
. . .
goto Exit;
. . .
c:
  c_finit();
b:
  b_finit();
a:
  a_finit();
Exit:
  return err;
}
A variace na podobné téma (ve Windows kernelu se dalo najít celkem běžně).
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Zdeno Sekerák 18. 08. 2019, 22:57:59
Goto? Nikdy. A to delam programatora vice jak 20 let.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Sivák 18. 08. 2019, 23:34:34
Ano. Na už zmíněný error handling. Víceméně jako náhradu výjimky. Jde asi o jediný celkem akceptovaný scénář pro goto.

Ještě se používá v konečných automatech a parserech, tam ho ovšem typicky nepíšete ručně, ale generujete.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: nula 19. 08. 2019, 07:46:56
Obcas, krome uz zminenych pripadu se hodi na vyskakovani z vicenasobne vnorenych smycek. Nekdy dost hodne. Na tom je obcas pekne poznat nezkuseneho programatora, ktery vyrobi strasne slozity a nepochopitelny bazmek, kde na prvni pohled vubec neni poznat co byl zamer, protoze ve skole se dozvedel, ze goto je zlo a ted ma strach ho pouzit. :)
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Zdeno Sekerák 19. 08. 2019, 08:56:31
Obcas, krome uz zminenych pripadu se hodi na vyskakovani z vicenasobne vnorenych smycek. Nekdy dost hodne. Na tom je obcas pekne poznat nezkuseneho programatora, ktery vyrobi strasne slozity a nepochopitelny bazmek, kde na prvni pohled vubec neni poznat co byl zamer, protoze ve skole se dozvedel, ze goto je zlo a ted ma strach ho pouzit. :)
Pouziti GOTO mi pripada jako "ted vyskoc z okna" ono to nejak dopadne. Misto: nech toho co delas, vyjdi dverma, zamkni a sejdi ze schodu dolu.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Kozzi 19. 08. 2019, 09:22:44
Obcas, krome uz zminenych pripadu se hodi na vyskakovani z vicenasobne vnorenych smycek. Nekdy dost hodne. Na tom je obcas pekne poznat nezkuseneho programatora, ktery vyrobi strasne slozity a nepochopitelny bazmek, kde na prvni pohled vubec neni poznat co byl zamer, protoze ve skole se dozvedel, ze goto je zlo a ted ma strach ho pouzit. :)

Tak ono nektere jazyky pro toto maji specialni syntaxi (break: navesti, priapdne break cislo_z_kolika_smycek_vyskocit) aby se nemuselo pouzit to zle skarede goto :-) .
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: nula 19. 08. 2019, 09:28:09
Obcas, krome uz zminenych pripadu se hodi na vyskakovani z vicenasobne vnorenych smycek. Nekdy dost hodne. Na tom je obcas pekne poznat nezkuseneho programatora, ktery vyrobi strasne slozity a nepochopitelny bazmek, kde na prvni pohled vubec neni poznat co byl zamer, protoze ve skole se dozvedel, ze goto je zlo a ted ma strach ho pouzit. :)
Pouziti GOTO mi pripada jako "ted vyskoc z okna" ono to nejak dopadne. Misto: nech toho co delas, vyjdi dverma, zamkni a sejdi ze schodu dolu.

To je poradny nesmysl,  C++ (nevim jak C, ale predpokladam, ze to bude stejny), je presne definovano jak se to bude chovat. Je to normalni vyskoceni ze vsech zanorenych scope. Zadne vyskakovani z okna, je to primy vychod ven. Promin, ale ty jsi dalsi takovy pripad, o kterem jsem mluvil....
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Sivák 19. 08. 2019, 09:35:17
Pouziti GOTO mi pripada jako "ted vyskoc z okna" ono to nejak dopadne.

Očividně jste dobře naučený to oblíbené "zapomeňte na goto". Skok uvnitř funkce je totiž v C naprosto legální a nemá žádné nepředvídatelné následky.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Kozzi 19. 08. 2019, 10:42:45
Obcas, krome uz zminenych pripadu se hodi na vyskakovani z vicenasobne vnorenych smycek. Nekdy dost hodne. Na tom je obcas pekne poznat nezkuseneho programatora, ktery vyrobi strasne slozity a nepochopitelny bazmek, kde na prvni pohled vubec neni poznat co byl zamer, protoze ve skole se dozvedel, ze goto je zlo a ted ma strach ho pouzit. :)
Pouziti GOTO mi pripada jako "ted vyskoc z okna" ono to nejak dopadne. Misto: nech toho co delas, vyjdi dverma, zamkni a sejdi ze schodu dolu.

To je poradny nesmysl,  C++ (nevim jak C, ale predpokladam, ze to bude stejny), je presne definovano jak se to bude chovat. Je to normalni vyskoceni ze vsech zanorenych scope. Zadne vyskakovani z okna, je to primy vychod ven. Promin, ale ty jsi dalsi takovy pripad, o kterem jsem mluvil....

Presne tak, akorat ze tusim u C narozdil od C++ ti to dovoli preskocit inicializace promennych, coz neni zrovna super ale pokud ma clovek zapnute warningy tak si toho vsimne u u toho C
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: novomente 19. 08. 2019, 10:45:12
Kdyz tedy pouziji goto uvnitr nejakeho bloku kodu a vyskocim z tohoto bloku, povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny? Nebo ho nechava nejak otevreny? Viz tento priklad:

Kód: [Vybrat]
int i, j;

for(i = 0; i < 10; ++i) {
for(j = 0; j < 20; ++j) {
if(j == 5)
goto vylez_z_cyklu;
}
}

vylez_z_cyklu: printf("j je rovno %d\n", j);
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Kozzi 19. 08. 2019, 12:24:27
Kdyz tedy pouziji goto uvnitr nejakeho bloku kodu a vyskocim z tohoto bloku, povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny? Nebo ho nechava nejak otevreny? Viz tento priklad:

Kód: [Vybrat]
int i, j;

for(i = 0; i < 10; ++i) {
for(j = 0; j < 20; ++j) {
if(j == 5)
goto vylez_z_cyklu;
}
}

vylez_z_cyklu: printf("j je rovno %d\n", j);

Samozrejme ze za ukonceny, proste si v tom miste odesel. Je to jako by si tam dal break; a za tim vnitrnim forem byl zase break;
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: ByCzech 19. 08. 2019, 12:39:00
Kdyz tedy pouziji goto uvnitr nejakeho bloku kodu a vyskocim z tohoto bloku, povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny? Nebo ho nechava nejak otevreny? Viz tento priklad:

Kód: [Vybrat]
int i, j;

for(i = 0; i < 10; ++i) {
for(j = 0; j < 20; ++j) {
if(j == 5)
goto vylez_z_cyklu;
}
}

vylez_z_cyklu: printf("j je rovno %d\n", j);

Co vám brání si to zkompilovat a pak to disasseblovat, aby jste viděl, jak to dopadlo?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Kozzi 19. 08. 2019, 13:02:39
Kdyz tedy pouziji goto uvnitr nejakeho bloku kodu a vyskocim z tohoto bloku, povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny? Nebo ho nechava nejak otevreny? Viz tento priklad:

Kód: [Vybrat]
int i, j;

for(i = 0; i < 10; ++i) {
for(j = 0; j < 20; ++j) {
if(j == 5)
goto vylez_z_cyklu;
}
}

vylez_z_cyklu: printf("j je rovno %d\n", j);

Co vám brání si to zkompilovat a pak to disasseblovat, aby jste viděl, jak to dopadlo?

Tak teoreticky mu muze chybet znalost ASM ;-)

https://godbolt.org/z/elNcJ8
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Kozzi 19. 08. 2019, 13:07:15
https://godbolt.org/z/elNcJ8

Jeste doporucuji si pohrat s argumentama pro kompilaci napriklad uz i pri -O1 se kompletne zrusi ten cyklus, jelikoz kompilator vi ze muze rovnou vypsat cislo 5
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: novomente 19. 08. 2019, 13:14:23
Kdyz tedy pouziji goto uvnitr nejakeho bloku kodu a vyskocim z tohoto bloku, povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny? Nebo ho nechava nejak otevreny? Viz tento priklad:

Kód: [Vybrat]
int i, j;

for(i = 0; i < 10; ++i) {
for(j = 0; j < 20; ++j) {
if(j == 5)
goto vylez_z_cyklu;
}
}

vylez_z_cyklu: printf("j je rovno %d\n", j);

Co vám brání si to zkompilovat a pak to disasseblovat, aby jste viděl, jak to dopadlo?

Tak teoreticky mu muze chybet znalost ASM ;-)

https://godbolt.org/z/elNcJ8

 :D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: ByCzech 19. 08. 2019, 14:04:32
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: robin martinez 19. 08. 2019, 15:33:25
To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

+1 je treba to brat tak, ze goto neni zadny zlo, to z nej muze udelat jen programator. Obecne by programatori mohli mit nejakej prehled o tom, jak vlastne funguje ulozeni dat v pameti, volani funkci apod. kraviny na urovni HW. Tuhle jsem se s jednim 'pro- programatorem' hadal, kdyz se me snazil presvedcit o tom, ze dnesni CPU zpracovavaji OOP kod lepe, nez kod funkcionalni. Marne chapal, ze cpu nezna neco jako 'oop kod'
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Mlocik97 19. 08. 2019, 15:43:22
Na to že som v Cečku programoval už relativne dosť, tak ja ani neviem o existencii "GOTO" v tomto jazyku. Takže si myslím, že je to absolutne nepoužívané a asi to má aj nejaký dôvod.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Sivák 19. 08. 2019, 17:03:20
Na to že som v Cečku programoval už relativne dosť, tak ja ani neviem o existencii "GOTO" v tomto jazyku. Takže si myslím, že je to absolutne nepoužívané a asi to má aj nejaký dôvod.

Důvodem je, že goto se dá snadno zneužít a tudíž je v rámci výuky zavedeno jednoduché pravidlo: "Nepoužívejte goto, nebo skončíte bez bodů".

Přečtěte si následující thread. Jsou tam všechny podstatné citace i ukázky.

https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: listoper 19. 08. 2019, 19:11:45
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: kozzi11 19. 08. 2019, 19:55:39
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)

Tak goto se cte skvele a o te praci se pise hned v nekolika odkazech co jsou tu ve vlakne. Ta prace je holt stara a jeji hodnota je minimalne spekulativni.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: listoper 19. 08. 2019, 20:59:52
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)

Tak goto se cte skvele a o te praci se pise hned v nekolika odkazech co jsou tu ve vlakne. Ta prace je holt stara a jeji hodnota je minimalne spekulativni.

Ta "prace" neni stara. Nas obor neni stary. Od ty doby co to napsal se v nasem oboru nic moc nezmenilo.
A nevim co znamena, ze hodnota je minimalne spekulativni... jakoze by se o ni nemelo moc spekulovat?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: nula 19. 08. 2019, 21:01:49
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)

Jo jasne, je lepsi se vyhybat ifum, ale pattern matching je cesta... haha, tak ty jsi to rozsekl frajere...
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: listoper 19. 08. 2019, 21:19:53
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)

Jo jasne, je lepsi se vyhybat ifum, ale pattern matching je cesta... haha, tak ty jsi to rozsekl frajere...
Co je spatneho na pattern matching?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: novomente 20. 08. 2019, 07:19:41
Jestli je goto v assembleru pouze instrukce JMP (a jeji vysledek ve strojovem kodu je vlastne take jenom skok na adresu), pak by melo goto teoreticky zkracovat strojovy kod, nez goto obchazet. Pokud platnost navesti (a tim i platnost goto) je pouze uvnitr funkce, nemelo by to sekat nejake dlouhe strojaky. Otazkou je, jestli se to kvuli rychlosti vyplati... viz dale...

V knize "Programovaci jazyk C" od K&R se pise (cituji): "Jazyk C poskytuje neomezeně zneužitelný příkaz goto a návěští, na která lze skákat. Formálně je příkaz goto vždzy nahraditelný a v praxi je téměř vždy jednoduché psát programy bez goto.", a o kus dále: "Existuje nicméně několik situací, kdy je možné goto použít."

Ony mozne pripady, kdy je goto MOZNE pouzit, byly zmineny v zacatku teto diskuse.

Dale na konci kapitoly o goto K&R pisou: "Kromě pár zde uvedených výjimek jsou programy používající goto složitější na pochopení a údržbu než programy bez goto. I když nechceme být příliš dogmatičtí, příkazy goto by měly být používány velice zřídka, nejlépe vůbec."

A jak je tedy na tom praxe? To je muj dotaz.


(citáty jsou z knihy: Programovací jazyk C; Brian W. Kernighan, Dennis M. Ritchie; Computer Press Brno 2013).
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Dráb 20. 08. 2019, 11:29:54
Citace
estli je goto v assembleru pouze instrukce JMP (a jeji vysledek ve strojovem kodu je vlastne take jenom skok na adresu), pak by melo goto teoreticky zkracovat strojovy kod, nez goto obchazet.

Ano, jedná se o jednu JMP instrukci (na ia32/x64, ale myslím, že na většině architektur to bude stejné).

Nemyslím, že by explicitní použití goto zdrojáky výrazně zkracovalo ve výše diskutovaných případech. Při vyskakování ze zanořeného cyklu ven vám ušetří pár podmínek (což obvykle je pár instrukcí).

Většinu kódu stejně netvoří skoky.

Co se týče té mojí ukázky, tam byste musel prostě místo goto volat ty finit funkce a pak dělat return. Nebo ten kód přepsat na něco jako:
Kód: [Vybrat]
err = a_init();
if (!err) {
  err = b_init();
  if (!err) {
    err = c_init();
   . . .

   }

    b_finit();
  }

  a_finit();
}

return err;
Tím se goto zbavíte, ale zase se tam přidává indentace, takže když těch init funkcí máte hodně, nedá se to číst ("ujíždí" to doprava). A někdo zase může preferovat ten způsob s goto.

Také nezapomeňte na to, že i když voláte ty finit funkce opakovaně, moc tím kód neprodulužujete, protože volání znamená jen pár instrukcí pro předání parametrů a instrukci CALL pro samotný skok na danou funkci.

Ta čitelnost je důležitá. Standardní konstrukty jako if, for, while, do-while, switch v sobě nějakou formu skoku mají ukrytou (podmíněnou či nepodmíněnou), ale vždy víte, kam se máte dívat, pokud třeba chcete vidět, co je za koncem cyklu (kudy to "vede" dál). Pokud budete používat goto a prostě skákat na různá návěští bez dodržování nějaké konvence, musíte si při čtení pamatovat, kde ta návěští jsou (a tak nějak si pamatovat ten graf možných skoků).
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Johnny 20. 08. 2019, 12:53:22
Tím se goto zbavíte, ale zase se tam přidává indentace, takže když těch init funkcí máte hodně, nedá se to číst ("ujíždí" to doprava). A někdo zase může preferovat ten způsob s goto.
Sice je to špatný příklad, kde by nemělo pro pár instrukcí smysl dělat nějakou optimalizaci...
Ale co je špatného na tomto:
Kód: [Vybrat]
err = a_init();
if (err) return err;
err = b_init();
if (err) return err;
err = c_init();
if (err) return err;
?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: gill 20. 08. 2019, 13:13:55
Tím se goto zbavíte, ale zase se tam přidává indentace, takže když těch init funkcí máte hodně, nedá se to číst ("ujíždí" to doprava). A někdo zase může preferovat ten způsob s goto.
Sice je to špatný příklad, kde by nemělo pro pár instrukcí smysl dělat nějakou optimalizaci...
Ale co je špatného na tomto:
Kód: [Vybrat]
err = a_init();
if (err) return err;
err = b_init();
if (err) return err;
err = c_init();
if (err) return err;
?

musíte testovat návratovou hodnotu funkce při každém volání. Goto zjednodušuje použití těch funkcí, kde může nastat chybový stav. Může vyskočit i z více úrovní volání.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Dráb 20. 08. 2019, 13:19:56
Tam je problém, že v případě, kdy selže třeba b_init musí mít vyšší vrstva kódu na paměti, že by měla zavolat a_finit.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Johnny 20. 08. 2019, 13:57:27
musíte testovat návratovou hodnotu funkce při každém volání. Goto zjednodušuje použití těch funkcí, kde může nastat chybový stav. Může vyskočit i z více úrovní volání.
Ano jistě, ale šlo mi spíš o to přímé return err, místo Goto Exit,
Tam je problém, že v případě, kdy selže třeba b_init musí mít vyšší vrstva kódu na paměti, že by měla zavolat a_finit.
Problém nevidím, může to ta vrstva poznat? O to v tom příkladu snad nešlo... Určitě by se to pak napsalo úplně jinak, ne?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: smrt28 20. 08. 2019, 14:18:00
Snad nikdy sem nevidel kod, kde by bylo GOTO nejak zneuzivano. IMO se cele GOTO trochu moc demonizuje. Pouziva se minimalne a kdyz uz, tak to na tom miste, kde se pouzilo, proste nevadi. Ucit deti, ze by GOTO nemely pouzivat asi nejaky smysl ma, ale obecne, kdyz nekdo zacne programovat a misto "BEGIN" a "END" si vybere GOTO, asi by se mel radeji venovat necemu jinemu.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: gill 20. 08. 2019, 14:46:44
musíte testovat návratovou hodnotu funkce při každém volání. Goto zjednodušuje použití těch funkcí, kde může nastat chybový stav. Může vyskočit i z více úrovní volání.
Ano jistě, ale šlo mi spíš o to přímé return err, místo Goto Exit,

myslel jsem, že se tu řeší, jak se takovým konstruktům vyhnout pomocí GOTO.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Johnny 20. 08. 2019, 15:05:53
musíte testovat návratovou hodnotu funkce při každém volání. Goto zjednodušuje použití těch funkcí, kde může nastat chybový stav. Může vyskočit i z více úrovní volání.
Ano jistě, ale šlo mi spíš o to přímé return err, místo Goto Exit,

myslel jsem, že se tu řeší, jak se takovým konstruktům vyhnout pomocí GOTO.
Dobře, záleží, jestli hledáme argumenty pro použití goto, nebo proti.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Michal Kubeček 20. 08. 2019, 22:12:05
musíte testovat návratovou hodnotu funkce při každém volání. Goto zjednodušuje použití těch funkcí, kde může nastat chybový stav. Může vyskočit i z více úrovní volání.
Ano jistě, ale šlo mi spíš o to přímé return err, místo Goto Exit,
To si můžete dovolit tam, kde nepotřebujete před návratem provést nějaký úklid. Samozřejmě jde použít i něco jako
Kód: [Vybrat]
        ret = init_foo();
        if (ret < 0) {
                /* cleanup */
                return ret;
        }
ale v případech, o kterých se tu bavíme, bude toho úklidu přibývat, jak bude přibývat provedených inicializací.
Tam je problém, že v případě, kdy selže třeba b_init musí mít vyšší vrstva kódu na paměti, že by měla zavolat a_finit.
Problém nevidím, může to ta vrstva poznat? O to v tom příkladu snad nešlo... Určitě by se to pak napsalo úplně jinak, ne?
Zkuste se podívat třeba sem (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv6/af_inet6.c#n971) na funkci inet6_init() a rozmyslete si, jak by ten kód vypadal, kdybyste se chtěl za každou cenu vyhnout použití goto.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Martin Dráb 20. 08. 2019, 22:20:12
Citace
Problém nevidím, může to ta vrstva poznat? O to v tom příkladu snad nešlo... Určitě by se to pak napsalo úplně jinak, ne?
Já se snažím psát funkce tak, aby když selžou, vrátily stav programu do stavu před svým voláním (tzn. uklidí po sobě). Pokud tedy vynecháte některé z finit volání, tak máte pravděpodobně resource leak.

Samozřejmě, můžete si pamatovat , že "když funkce X selže, musím někde zavolat a_finit, protože ona to neudělala"; podle mě pak ale kód přestává být srozumitelný.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: kozzi11 20. 08. 2019, 23:38:52
Citace
Problém nevidím, může to ta vrstva poznat? O to v tom příkladu snad nešlo... Určitě by se to pak napsalo úplně jinak, ne?
Já se snažím psát funkce tak, aby když selžou, vrátily stav programu do stavu před svým voláním (tzn. uklidí po sobě).

No to je důvod proč preferuji pure funkce. Protože vím že nemohou ovlivnit okolní stav jinak než je očekáváno (to znamená nijak).
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Michal Kubeček 21. 08. 2019, 05:41:08
Samozřejmě, můžete si pamatovat , že "když funkce X selže, musím někde zavolat a_finit, protože ona to neudělala"; podle mě pak ale kód přestává být srozumitelný.
Hlavně rychle přestane být udržovatelný. Bude potřeba pořád hlídat, jestli na to někdo nezapomněl. Když se bude volat na deseti místech, tak aby si na to člověk radši napsal wrapper - ale když tu funkci budu pokaždé volat přes (stejný) wrapper, tím spíš vynikne, že cleanup měl být rovnou v té funkci. A ani z logického hlediska to nedává smysl, pokud funkce něco alokuje, má to po návratu zůstat alokované jen v případě, že volající potřebuje, aby to alokované zůstalo.

Navíc jsme se tu bavili o případech, kdy těch inicializačních kroků je víc, selhat může kterýkoli z nich a volající obecně neví, který to byl a co je potřeba uklidit. Nemluvě o tom, že v praxi to často nebude jen prosté a_init() ... a_finit(), protože se úklidové funkci bude předávat pointer na to, co se má uklidit, který volající ani nebude mít k dispozici.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: nula 21. 08. 2019, 07:53:41
:D compilace/disassembling je docela dobry napad  :)

Ale jak uz bylo receno, brani mi v tom znalost ASM. Mimochodem, taky bych chtel trochu ten ASM okusit.

https://godbolt.org/z/elNcJ8 (https://godbolt.org/z/elNcJ8) - to je dobry link, diky moc  :)

To je škoda, by jste viděl, že to je prostě strojová instrukce jmp (skok na adresu) a že těch jmp je tam normálně víc. Jak píše Linus Torvalds: Každý if je goto.

Proto je lepsi se if-um vyhybat :-). Taky proto mozna vznikaji jazyky ktery maji polymorphic dispatch, pattern matching a podobne.... (a ano je to taky prevleceny goto... )

Podle me se to proste hur cte...
Kompiler at si tam naseka jmp kolik chce.... ale proc to mam cist ja?

A jeste sem tu nevidel link na https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf)

Jo jasne, je lepsi se vyhybat ifum, ale pattern matching je cesta... haha, tak ty jsi to rozsekl frajere...
Co je spatneho na pattern matching?

Za mne vubec nic, ale ja taky neplivu na ify. Mi prijde vtipne, ze plives na obecne vyhodnocovani podminky, ale  vyhodnocovani konkretni podminky a to konkretne pattern matchingu ti prijde v poradku.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: nula 21. 08. 2019, 07:57:03
Tím se goto zbavíte, ale zase se tam přidává indentace, takže když těch init funkcí máte hodně, nedá se to číst ("ujíždí" to doprava). A někdo zase může preferovat ten způsob s goto.
Sice je to špatný příklad, kde by nemělo pro pár instrukcí smysl dělat nějakou optimalizaci...
Ale co je špatného na tomto:
Kód: [Vybrat]
err = a_init();
if (err) return err;
err = b_init();
if (err) return err;
err = c_init();
if (err) return err;
?

Kde a jak zavolate a_finit(), b_finit(), atd. ?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Idris 21. 08. 2019, 09:15:58
Citace
Problém nevidím, může to ta vrstva poznat? O to v tom příkladu snad nešlo... Určitě by se to pak napsalo úplně jinak, ne?
Já se snažím psát funkce tak, aby když selžou, vrátily stav programu do stavu před svým voláním (tzn. uklidí po sobě).

No to je důvod proč preferuji pure funkce. Protože vím že nemohou ovlivnit okolní stav jinak než je očekáváno (to znamená nijak).
Můžou měnit kontext.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Ondřej Novák 21. 08. 2019, 09:49:43
Nejznámější variantou goto je switch-case. Jinak v C++ je to složitější když v rámci skoku preskakuju inicializaci objektů - není to fakt dobrý nápad a týká se to i switch case. Naštěstí překladač to oznámí. Takže je fakt dobré sahat na goto až je to opravdu nutné

Pokud při skoku opouštím blok kde končí platnost některých proměnných, zavolají se destruktory - takže obyčejný JMP to není.

(Právě kvůli finalizaci mám rád koncept RAII - pak goto nepotřebuju)
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Ondřej Surý 13. 10. 2019, 08:00:18
> povazuje prekladac zmineny blok kodu (ze ktereho jsem vyskocil) za ukonceny?

Co to pro vás znamená?  Pokud vyskočíte ze scope, tak jste vyskočil ze scope.  A pokud nepoužíváte nějaké GNU extensions jako je __attribute__((cleanup(...))), tak opuštění scope v C nic moc neznamená.
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Ondřej Surý 13. 10. 2019, 08:13:00
Citoval bych tady úryvek z knihy Modern C (https://modernc.gforge.inria.fr/) k použití goto pro error handling:

Citace
The use of goto and similar jumps in programming languages has been subject to intensive debate, starting from an article by Dijkstra [1968]. You will still find people who seriously object to code as it is given here, but let us try to be pragmatic about that: code with or without goto can be ugly and hard to follow. The main idea is to have the “normal” control flow of the function be mainly undisturbed and to clearly mark changes to the control flow that only occur under exceptional circumstances with a goto or return.

Na straně 240-249 je pak o něco komplikovanější příklad, kde použití goto dává smysl...
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: BoneFlute 14. 10. 2019, 21:57:19
No to je důvod proč preferuji pure funkce. Protože vím že nemohou ovlivnit okolní stav jinak než je očekáváno (to znamená nijak).
Můžou měnit kontext.
Můžeš to rozvést?
Název: Re:Použití příkazu GOTO v jazyku C
Přispěvatel: Idris 14. 10. 2019, 22:43:55
No to je důvod proč preferuji pure funkce. Protože vím že nemohou ovlivnit okolní stav jinak než je očekáváno (to znamená nijak).
Můžou měnit kontext.
Můžeš to rozvést?
To byla jen poznámka na okraj, že i pure funkce můžou efektivně měnit okolní kontext, když je typový systém dostatečně silný, záleží na tom, jak se řetězí. Celé FP je postavené na tom, že funkce jsou sice pure (což je omezení), ale typový systém je natolik silný, že lze v případě nutnosti měnit vnější kontext, čímž se ono “omezení” kompenzuje.