2012-11-03, 08:12
  #49
Medlem
klurigklurings avatar
Citat:
Ursprungligen postat av mongomannen
Jag förstår inte riktigt hur du menar här. Om du skulle kunna ge ett exempel på kod som ballar ur skulle jag vara tacksam.
Kan försöka förklara med lite språkneutral pseudokod som inte gör nåt vettigt. Har ännu inte träffat på språk då motsvarande konstruktion inte går att göra och alla jobbar på likartad sätt.

Kod:
A-HUVUDSLINGA (main)
    UFÖR B-RUTIN 
    UTFÖR C-RUTIN
A-END 
    STOP RUN

B-RUTIN
    bearbetning 1, vadsomhelst
    
    IF (ett visst resultat)
         GOTO C-RUTIN
    ENDIF

    fortsatt bearbetning
B-END

C-RUTIN
    annat
C-END
.
.
N-RUTIN
N-END
Kompilatorn skapar en start och en slutadress för varje avsnitt som runtimefilen använder enligt en bestämd schema. När B-END är klar ska C-RUTIN genomlöpas. Petar man in GOTO enligt ovan kommer man aldrig till slutadressen i B-RUTIN och programmet kommer att skena. GOTO B-END borde det stå. Ännu bättre utan GOTO om man gör om if satsen och villkorar ”fortsatt bearbetning" istället.
__________________
Senast redigerad av klurigkluring 2012-11-03 kl. 08:14.
Citera
2012-11-03, 11:32
  #50
Medlem
Citat:
Ursprungligen postat av klurigkluring
Kompilatorn skapar en start och en slutadress för varje avsnitt som runtimefilen använder enligt en bestämd schema. När B-END är klar ska C-RUTIN genomlöpas. Petar man in GOTO enligt ovan kommer man aldrig till slutadressen i B-RUTIN och programmet kommer att skena. GOTO B-END borde det stå. Ännu bättre utan GOTO om man gör om if satsen och villkorar ”fortsatt bearbetning" istället.

Nej, så fungerar det inte. Programmet pushar upp en adress att återvända till på stacken och hoppar till den rutin som anropas. Det finns inga slutadresser i den bemärkelsen att de måste passeras i en kronologisk ordning, även om C-standarden gör det svårt att komma ifrån. I ASM är det inga problem att leka med programflödet på detta vis.

Kompilatorn kan inte bygga detta exempel dock. Labels når inte utanför respektive funktions-scope, så du får ett fel på att labeln C-RUTIN inte är definierad i B-RUTIN.
Citera
2012-11-03, 13:34
  #51
Medlem
Citat:
Ursprungligen postat av klurigkluring
Kan försöka förklara med lite språkneutral pseudokod som inte gör nåt vettigt. Har ännu inte träffat på språk då motsvarande konstruktion inte går att göra och alla jobbar på likartad sätt.

Kod:
A-HUVUDSLINGA (main)
    UFÖR B-RUTIN 
    UTFÖR C-RUTIN
A-END 
    STOP RUN

B-RUTIN
    bearbetning 1, vadsomhelst
    
    IF (ett visst resultat)
         GOTO C-RUTIN
    ENDIF

    fortsatt bearbetning
B-END

C-RUTIN
    annat
C-END
.
.
N-RUTIN
N-END
Kompilatorn skapar en start och en slutadress för varje avsnitt som runtimefilen använder enligt en bestämd schema. När B-END är klar ska C-RUTIN genomlöpas. Petar man in GOTO enligt ovan kommer man aldrig till slutadressen i B-RUTIN och programmet kommer att skena. GOTO B-END borde det stå. Ännu bättre utan GOTO om man gör om if satsen och villkorar ”fortsatt bearbetning" istället.
Nu handlade ju iofs tråden om goto i c++, och standarden garanterar korrekt stack-unwinding vid användning av goto. Och som FaderBerg sa ovan, du kan inte hoppa mellan två funktionsblock med goto.
Det största problemet med goto är saker som t.ex
Kod:
int main()
{
	int a = 1;
	if(a)
		goto skip_b;
	int b = 2;
skip_b:
	int c = a * b;

	return 0;
}
GCC ger ett kompileringsfel, och om jag minns rätt ska inte standarden tillåta såna saker. MSVC ger inte ens en varning på standardvarningsnivån.
Citera
2012-11-03, 14:39
  #52
Medlem
Weeblies avatar
Citat:
Ursprungligen postat av mongomannen
Nu handlade ju iofs tråden om goto i c++, och standarden garanterar korrekt stack-unwinding vid användning av goto. Och som FaderBerg sa ovan, du kan inte hoppa mellan två funktionsblock med goto.
Det största problemet med goto är saker som t.ex
Kod:
int main()
{
	int a = 1;
	if(a)
		goto skip_b;
	int b = 2;
skip_b:
	int c = a * b;

	return 0;
}
GCC ger ett kompileringsfel, och om jag minns rätt ska inte standarden tillåta såna saker. MSVC ger inte ens en varning på standardvarningsnivån.

Är du säker på att koden verkligen kompilerar med MSVC?

C++ standarden säger under 6.7.3:

"It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type and is declared without an initializer."

ps. Anmärk att detta verkar vara tillåtet enligt C-standarden så det är mycket möjligt att du har stött på en MSVC "language extension" för PODs (MSVC är inte en renodlad C eller C++ kompilator utan plockar lite från båda världarna). Du bör kompilera med "/Za" flaggan för att undvika sådant (i.e. i stil med GCC's "-ansi"/"-pedantic").
__________________
Senast redigerad av Weeblie 2012-11-03 kl. 15:00.
Citera
2012-11-03, 17:08
  #53
Medlem
Citat:
Ursprungligen postat av Drubas
Om vi skulle komma på någon som använder labels på företaget, så skulle vi stena honom till döds och slänga liket på tunnelbanan

Jag använde GOTO rätt flitigt när jag för länge sedan lekte med C++, men jag har aldrig känt ett behov av det i Java.

Klart att man kan komma in i legacy-kod där man inte har annat alternativ än att försöka forma bajskorven, men utifrån ett "optimalt" perspektiv så borde all ny kod kunna klara sig utan GOTO?
Vad använder ni då? return?
Citera
2012-11-04, 00:54
  #54
Medlem
Citat:
Ursprungligen postat av Weeblie
Är du säker på att koden verkligen kompilerar med MSVC?

C++ standarden säger under 6.7.3:

"It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type and is declared without an initializer."

ps. Anmärk att detta verkar vara tillåtet enligt C-standarden så det är mycket möjligt att du har stött på en MSVC "language extension" för PODs (MSVC är inte en renodlad C eller C++ kompilator utan plockar lite från båda världarna). Du bör kompilera med "/Za" flaggan för att undvika sådant (i.e. i stil med GCC's "-ansi"/"-pedantic").
Du har rätt, det var en extension.
cl.exe utan switchar tillåter det utan varning.
cl /W4 (eller /Wall) ger "warning C4701: potentially uninitialized local variable 'b' used"
cl /Za ger "error C2362: initialization of 'b' is skipped by 'goto skip_b'"

Personligen så tycker jag nog att den varningen borde ligga under nivå 3 som är default. Att använda oinitierade variabler kan ju vara en ganska allvarlig bugg.
Citera
2012-11-24, 01:16
  #55
Medlem
*sn0wflake*s avatar
Citat:
Ursprungligen postat av FaderBerg
Jag använder goto flitigt i C. Mest för att avbryta till slutet av funktionerna vid fel.
[PHP]int main(void) {

int ret = 1; /* assume failure */
char* string = NULL;

if ((string = malloc(10)) == NULL) {
fprintf(stderr, "memory allocation error\n");
goto exit_main;
}

if (!test) {
fprintf(stderr, "test failed\n");
goto exit_main;
}

ret = 0;

exit_main:

if (string) free(string);

return ret;

}[/PHP]

Det går att fixa utan gotos, men jag tycker att detta är betydligt enklare och överskådligare.

Kod:
int main(void) {

    int   ret = 1; /* assume failure */
    char* string = NULL;

do {
    
    if ((string = malloc(10)) == NULL) {
        fprintf(stderr, "memory allocation error\n");
        break;
    }

    if (!test) {
        fprintf(stderr, "test failed\n");
        break;
    }

    ret = 0;
    
} while (0);

    if (string) free(string);

    return ret;
    
}

Ytterligare ett alternativ för att undvika goto. Jag är dock inte emot gotos, men använder dem mycket sparsamt. Det finns tillfällen då gotos är bästa lösningen. Denna implementation av qsort() (quicksort) är ett exempel på vettig användning av gotos:

http://www.jbox.dk/sanos/source/lib/qsort.c.html
__________________
Senast redigerad av *sn0wflake* 2012-11-24 kl. 01:22.
Citera
2012-11-24, 09:19
  #56
Medlem
Citat:
Ursprungligen postat av *sn0wflake*
Kod:
int main(void) {

    int   ret = 1; /* assume failure */
    char* string = NULL;

do {
    
    if ((string = malloc(10)) == NULL) {
        fprintf(stderr, "memory allocation error\n");
        break;
    }

    if (!test) {
        fprintf(stderr, "test failed\n");
        break;
    }

    ret = 0;
    
} while (0);

    if (string) free(string);

    return ret;
    
}

Det där var faktiskt förbannat snyggt. Tack för den...

Om jag måste undvika gotos, så får det bli på det här sättet.
Citera
2012-12-02, 01:12
  #57
Medlem
Alltså, de fallen som dök upp här hade ju passat perfekt att hantera genom att kasta ett undantag, som man sedan fångar i en högre liggande catch.
För övrigt så vägrar jag hålla med om att program som innehåller GOTO använder strukturerad programmering.
Citera
2013-01-05, 07:20
  #58
Medlem
Citat:
Ursprungligen postat av Oldskool
Alltså, de fallen som dök upp här hade ju passat perfekt att hantera genom att kasta ett undantag, som man sedan fångar i en högre liggande catch.
Helt sant när det gäller felhanteringen, men känns det inte lite overkill för att hoppa ur en nästlad loop?
Citat:
För övrigt så vägrar jag hålla med om att program som innehåller GOTO använder strukturerad programmering.
Då är du ju bara vrång.
Citera
2013-01-05, 18:33
  #59
Medlem
christerys avatar
Ser inte behovet av fanstyget. sista goto jag använde var i basic som följde med DOS.

Tänk igenom vad som skall göras så slipper man hopp. Behöver man hoppa så tjorvar man bara till det. Vill inte tillbaka till spagettiprogrammeringen.

Använder ni globala variabler åxå när ni kan (större scope än nödvändigt)

Jo det är en utopi - men den är i alla fall min
__________________
Senast redigerad av christery 2013-01-05 kl. 18:36.
Citera
2013-01-05, 19:11
  #60
Medlem
Citat:
Ursprungligen postat av christery
Ser inte behovet av fanstyget. sista goto jag använde var i basic som följde med DOS.

Tänk igenom vad som skall göras så slipper man hopp. Behöver man hoppa så tjorvar man bara till det. Vill inte tillbaka till spagettiprogrammeringen.

Använder ni globala variabler åxå när ni kan (större scope än nödvändigt)

Jo det är en utopi - men den är i alla fall min
Är du här och sprider fördomar nu?
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in