Warum brauchen Sie in C eine Anweisung nach einem goto-Label?
Lesezeit: 4 Minuten
Anton Delprado
Ich schreibe etwas C-Code und in meinem Code habe ich zwei verschachtelte Schleifen. Unter einer bestimmten Bedingung will ich break aus der inneren Schleife und continue die äußere Schleife. Ich habe versucht, dies mit einem Label am Ende des Codes der äußeren Schleife zu erreichen, und unter der Bedingung, goto dieses Etikett. Jedoch gcc gibt einen Fehler aus, dass ich am Ende einer zusammengesetzten Anweisung kein Label haben kann. Warum nicht?
Anmerkung 1: Dies ist keine switch Aussage u das Frage wurde an anderer Stelle beantwortet.
Anmerkung 2: Dies ist keine Frage des Stils und ob ich es verwenden sollte oder nicht goto stattdessen Anweisungen oder bedingte Variablen.
BEARBEITEN: Die Leute haben nach einem Beispiel gefragt, und ich kann ein etwas einfaches Beispiel geben, um zu überprüfen, ob ein Array ein Unterarray eines anderen Arrays ist
int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...};
int superIndex, subIndex;
for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1)
{
for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1)
if (superArray[superIndex+subIndex] != subArray[subIndex])
goto break_then_continue;
// code that executes if subArray is a sub array
break_then_continue:
}
Können Sie ein kleines Programm bereitstellen, das die erhaltene Fehlermeldung reproduziert?
– Sarnold
16. März 2012 um 2:10 Uhr
Viel Glück und achten Sie auf Velociraptoren
– Wim
16. März 2012 um 2:15 Uhr
Ich glaube, ich bin einfach nicht neugierig genug. Mein überragendes Gefühl dabei ist, dass Sie es einfach tun.
– Paul Sanders
15. Juli 2018 um 14:05 Uhr
Filip Roséen – Refp
Im Standard wird explizit gesagt, dass Labels zu einer Anweisung gehören, daher ein einfaches Semikolon (;) nach Ihrem Label kann das Problem umgehen, auf das Sie stoßen, da dies als Aussage gilt.
Es gibt sogar ein Beispiel für die Verwendung eines “leer“1 Aussage ein 6.8.3/6.
BEISPIEL 3 Eine Null-Anweisung kann auch verwendet werden, um ein Label direkt vor dem schließenden } einer zusammengesetzten Anweisung zu übertragen
while (loop1) {
/* ... */
while (loop2) {
/* ... */
if (want_out)
goto end_loop1;
/* ... */
}
/* ... */
end_loop1: ;
}
1In der Norm wird dies als a bezeichnet null statement.
+1 Tolle Antwort. Ich liebe das Beispiel, das direkt aus dem Standard stammt.
– Kaleb
16. März 2012 um 2:24 Uhr
Danke für die tolle Antwort. ich suchte warumgcc funktioniert so, wie es nicht funktioniert, wie man es umgeht. Ihre Antwort deutet jedoch darauf hin, dass es einfach so ist, wie c geschrieben wird. Dies ist größtenteils ein Erbe aus der Zeit, als die c-Kompilierung nur eine geringfügige Abstraktion des Assembler-Codes war.
– Anton Delprado
16. März 2012 um 2:36 Uhr
@AntonDelprado Es ist eigentlich ziemlich einfach, goto platziert das Label vor dem Befehl/Ausdruck, und wenn es so etwas nicht gibt, kann man nirgendwo springen. Diese leere Anweisung wird verwendet, damit dies möglich ist. Auf diese Weise springen Sie auf ein harmloses Äquivalent der NOP-Assembly-Funktion (no operation).
– Tomás Pruzina
16. März 2012 um 6:17 Uhr
Wow, das bedeutet a switch Aussage ist nur ein Haufen von gotos. Ich denke, es ist offensichtlich, aber ich habe nie darüber nachgedacht. Jeder, der dogmatisch denunziert goto–und will konsequent bleiben–sollte auch den Konsum beklagen switch. Entweder das, oder sich mit der Nutzung begnügen goto Als ein superbreak;
– SO_fix_the_vote_sorting_bug
8. Juli 2017 um 1:01 Uhr
@ jdk1.0 Noch schlimmer, switch ist ein berechnet goto (dh eines, bei dem das Ziel dynamisch ist). 🙂
– Melpomen
15. Juli 2018 um 12:46 Uhr
Sie müssen lediglich schreiben:
label: ;
Das Semikolon ist eine leere Anweisung. Sie brauchen es, weil die Sprache so definiert ist; Sie müssen zu einer Anweisung gehen, auch wenn diese leer ist.
for (int i = 0; i < N; i++)
{
for (int j = 0; i < M; j++)
{
...
if (some_condition)
goto continue_loop1;
...
}
continue_loop1: ;
}
Über die Einkerbung auf dem Etikett kann man streiten.
Beachten Sie auch, dass eine Deklaration, selbst mit einer Initialisierung, keine Anweisung ist, die gekennzeichnet werden kann: label1: int x = function(y, z); ist ungültig.
– Jonathan Leffler
6. November 2013 um 15:49 Uhr
ouah
Das Etikett sollte auf eine Aussage verweisen.
C befiehlt dies:
(C99, 6.8.1 Labeled Statements p4) ” Jeder Anweisung kann ein Präfix vorangestellt werden, das einen Bezeichner als Labelnamen deklariert.”
In Ihrem Fall können Sie eine Null-Anweisung verwenden:
void foo(void)
{
goto bla;
bla:
;
}
Null-Anweisungen führen keine Operation aus.
Oder Sie können auch eine zusammengesetzte Anweisung (einen Block) verwenden, wenn Sie Deklarationen haben:
void foo(void)
{
goto bla;
bla:
{
int x = 42;
printf("%d\n", x);
}
}
13853600cookie-checkWarum brauchen Sie in C eine Anweisung nach einem goto-Label?yes
Können Sie ein kleines Programm bereitstellen, das die erhaltene Fehlermeldung reproduziert?
– Sarnold
16. März 2012 um 2:10 Uhr
Viel Glück und achten Sie auf Velociraptoren
– Wim
16. März 2012 um 2:15 Uhr
Ich glaube, ich bin einfach nicht neugierig genug. Mein überragendes Gefühl dabei ist, dass Sie es einfach tun.
– Paul Sanders
15. Juli 2018 um 14:05 Uhr