Warum brauchen Sie in C eine Anweisung nach einem goto-Label?

Lesezeit: 4 Minuten

Benutzer-Avatar
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

Benutzer-Avatar
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 “leer1 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: ;
}

1 In der Norm wird dies als a bezeichnet null statement.


6.8.1 Beschriftete Aussagen

Syntax
  1 labeled-statement:
      identifier : statement
      case constant-expression : statement
      default : statement

Beachte das statement ist im obigen Zitat nicht optional.


  • +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 warum gcc 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

Benutzer-Avatar
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);
    }
 }

1385360cookie-checkWarum brauchen Sie in C eine Anweisung nach einem goto-Label?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy