Použití příkazu GOTO v jazyku C

Re:Použití příkazu GOTO v jazyku C
« Odpověď #15 kdy: 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


Re:Použití příkazu GOTO v jazyku C
« Odpověď #16 kdy: 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

Re:Použití příkazu GOTO v jazyku C
« Odpověď #17 kdy: 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 - to je dobry link, diky moc  :)

ByCzech

  • *****
  • 1 848
    • Zobrazit profil
    • E-mail
Re:Použití příkazu GOTO v jazyku C
« Odpověď #18 kdy: 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 - 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.

robin martinez

  • *****
  • 1 138
  • Have you hugged your toilet today?
    • Zobrazit profil
    • Null Storage
    • E-mail
Re:Použití příkazu GOTO v jazyku C
« Odpověď #19 kdy: 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'
One machine can do the work of fifty ordinary men. No machine can do the work of one extraordinary man.

I do Linux, Hardware and spaghetti code in PHP, Python and JavaScript


Mlocik97

  • *****
  • 830
  • Ubunťák, JS dev.
    • Zobrazit profil
    • E-mail
Re:Použití příkazu GOTO v jazyku C
« Odpověď #20 kdy: 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.

Re:Použití příkazu GOTO v jazyku C
« Odpověď #21 kdy: 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/

Re:Použití příkazu GOTO v jazyku C
« Odpověď #22 kdy: 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 - 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

Re:Použití příkazu GOTO v jazyku C
« Odpověď #23 kdy: 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 - 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

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.

Re:Použití příkazu GOTO v jazyku C
« Odpověď #24 kdy: 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 - 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

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?

nula

Re:Použití příkazu GOTO v jazyku C
« Odpověď #25 kdy: 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 - 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

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

Re:Použití příkazu GOTO v jazyku C
« Odpověď #26 kdy: 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 - 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

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?

Re:Použití příkazu GOTO v jazyku C
« Odpověď #27 kdy: 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).

Re:Použití příkazu GOTO v jazyku C
« Odpověď #28 kdy: 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ů).

Re:Použití příkazu GOTO v jazyku C
« Odpověď #29 kdy: 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;
?