Kann eine ‘for’-Schleife innerhalb einer ‘for’-Schleife denselben Zählervariablennamen verwenden?

Lesezeit: 3 Minuten

Benutzeravatar von Uclydde
Uclydde

Kann ich dieselbe Zählervariable für a verwenden for Schleife innerhalb von a for Schleife?

Oder beeinflussen sich die Variablen gegenseitig? Sollte der folgende Code eine andere Variable für die zweite Schleife verwenden, wie z joder ist i fein?

for(int i = 0; i < 10; i++)
{
  for(int i = 0; i < 10; i++)
  {
  }
}

  • Es ist verwirrend – es würde bei einer Codeüberprüfung nicht an mir vorbeikommen. Aber es ist legitim. Es gibt zwei verschiedene Variablen, die beide aufgerufen werden i, mit unterschiedlichen Reichweiten. Verwenden -Wshadow mit GCC, um solche Probleme automatisch gemeldet zu bekommen.

    – Jonathan Leffler

    27. Juli 2018 um 0:26 Uhr

  • Das wundert mich -Wshadow ist nicht enthalten -Wall.

    – linksherum

    27. Juli 2018 um 7:57 Uhr

  • @leftaroundabout -Wshadow warnt auch vor dem Shadowing globaler Variablen, was in größeren Projekten leicht störend werden kann.

    – Kubisch

    27. Juli 2018 um 9:43 Uhr

  • @leftaroundabout sogar noch überraschender -Wextra beinhaltet nicht -Wshadow. Ich denke, es ist in einigen Projekten üblich genug, oder einige gcc Entwickler lieben Shadowing als Codierungsstil, um zu rechtfertigen, dass er so weggelassen wird.

    – Hyde

    27. Juli 2018 um 10:34 Uhr

  • @leftaroundabout In Anlehnung an das, was Cubic sagte, -Wshadow hat eine horrende Falsch-Positiv-Rate, was es völlig nutzlos macht. Scope existiert aus einem bestimmten Grund, und Shadowing ist es a priori nicht problematisch. Jetzt -Wshadow-local (Hinweis: nicht -Wshadow=local) ist sehr unterschiedlich. Aber leider hat sich GCC bisher geweigert, es in den Trunk aufzunehmen (obwohl es anscheinend Abzweigungen von GCC gibt, die es enthalten).

    – Konrad Rudolf

    27. Juli 2018 um 10:41 Uhr


Sie können denselben Namen (Bezeichner) verwenden. Es wird ein anderes Objekt sein. Sie werden sich nicht gegenseitig beeinflussen. Innerhalb der inneren Schleife gibt es keine Möglichkeit, auf das in der äußeren Schleife verwendete Objekt zu verweisen (es sei denn, Sie treffen spezielle Vorkehrungen dafür, indem Sie beispielsweise einen Zeiger darauf angeben).

Dies ist im Allgemeinen schlechter Stil, anfällig für Verwechslungen und sollte vermieden werden.

Die Objekte sind nur dann verschieden, wenn das innere separat definiert wird, wie bei der int i du hast gezeigt. Wenn derselbe Name verwendet wird, ohne ein neues Objekt zu definieren, verwenden die Schleifen dasselbe Objekt und stören sich gegenseitig.

  • Die Verwendung von for(i) und for(j) verschachtelt und innerhalb von i++ erhöht die Variable der äußeren Schleife. Was Sie sagen, ist jedoch richtig, wenn Sie in beiden Schleifen denselben Bezeichner verwenden, da es sich um Variablen mit unterschiedlichem Gültigkeitsbereich handelt.

    – KYL3R

    27. Juli 2018 um 11:28 Uhr


  • @BloodGain: „Objekt“ ist ein technischer Begriff, der im C-Standard verwendet wird. Ich habe es hier bewusst eingesetzt.

    – Eric Postpischil

    27. Juli 2018 um 21:27 Uhr

  • @EricPostpischil: Ah, ich verstehe, ja. Ich war mir dieser Definition im Standard nicht bewusst und hatte Angst, dass sie für neue Programmierer irreführend wäre (da dies ganz klar eine Anfängerfrage ist), da C keine “Objekte” in dem Sinne hat, wie wir den Begriff allgemein verwenden. Ich sehe es im C11-Standard, und jetzt bin ich neugierig, ob es vor C11 so definiert war.

    – Blutgewinn

    27. Juli 2018 um 21:32 Uhr

  • Es war. Im C99-Standard ist es 3,14 statt 3,15. Also keine Entschuldigung meinerseits. Das wird mich lehren, dich zu hinterfragen <:-|

    – Blutgewinn

    27. Juli 2018 um 21:36 Uhr

  • Allgemeiner: Nichts hindert Sie daran, einen Variablennamen in einem verschachtelten Gültigkeitsbereich wiederzuverwenden. Außer natürlich die Angst vor Gottes Strafe für das Schreiben von verwirrendem Code.

    – Isaac Rabinovitch

    2. August 2018 um 23:48 Uhr

Benutzeravatar von Sergey Kalinichenko
Sergej Kalinitschenko

Erstens ist dies absolut legal: Der Code wird kompiliert und ausgeführt, wobei der Hauptteil der verschachtelten Schleife 10 × 10 = 100 Mal wiederholt wird. Schleifenzähler i innerhalb der verschachtelten Schleife wird ausblenden der Zähler der äußeren Schleife, also würden die beiden Zähler unabhängig voneinander inkrementiert.

Da die äußere i ausgeblendet ist, hätte der Code im Körper der verschachtelten Schleife nur Zugriff auf den Wert von i der verschachtelten Schleife, nicht i aus der äußeren Schleife. In Situationen, in denen die verschachtelte Schleife keinen Zugriff auf die äußere benötigt i ein solcher Code könnte durchaus gerechtfertigt sein. Dies wird jedoch wahrscheinlich zu mehr Verwirrung bei den Lesern führen, daher ist es eine gute Idee, das Schreiben eines solchen Codes zu vermeiden, um „Wartungsverpflichtungen“ zu vermeiden.

Notiz: Obwohl die Zählervariablen beider Schleifen den gleichen Bezeichner haben isie bleiben zwei unabhängige Variablen, dh Sie sind nicht Verwenden Sie in beiden Schleifen dieselbe Variable. Es ist auch möglich, dieselbe Variable in beiden Schleifen zu verwenden, aber der Code wäre schwer lesbar. Hier ist ein Beispiel:

for (int i = 1 ; i < 100 ; i++) {
    for ( ; i % 10 != 0 ; i++) {
        printf("%02d ", i);
    }
    printf("%d\n", i);
}

Jetzt verwenden beide Schleifen dieselbe Variable. Es dauert jedoch eine Weile, um herauszufinden, was dieser Code tut, ohne ihn zu kompilieren (Demo);

  • Da die Frage als “mit derselben Zählervariable” formuliert ist, möchte ich auch darauf hinweisen, dass die Beschattung nur stattfindet, wenn die Neudefinition auftritt. Weglassen der int in der inneren for-Schleife, dh die tatsächliche Verwendung derselben Zählervariable, bewirkt, dass die äußere Schleife nur einmal ausgeführt wird, da die innere Schleife verlassen wird i == 10. Dies ist trivial, aber ich dachte, es liefert eine Klärung, wenn man bedenkt, wie die Frage gestellt wurde

    – Easton Bornemeier

    27. Juli 2018 um 0:04 Uhr


  • @EastonBornemeier Sie haben Recht, ich dachte mir, ich sollte das Problem “dieselbe Variable” im Hauptteil der Antwort ansprechen. Vielen Dank!

    – Sergej Kalinitschenko

    27. Juli 2018 um 0:31 Uhr

  • @EricPostpischil “Variable Shadowing” ist ein offizieller Begriff, komplett mit einer eigenen Seite auf Wikipedia. Ich habe die Antwort jedoch so aktualisiert, dass sie mit dem Wortlaut des Standards übereinstimmt. Vielen Dank!

    – Sergej Kalinitschenko

    27. Juli 2018 um 0:39 Uhr

  • @dasblinkenlight: Eigentlich hatte ich einen Gehirnkrampf wegen der Richtung, und der innere Name überschattet den äußeren Namen. Mein vorheriger Kommentar war in dieser Hinsicht falsch. Entschuldigen Sie. (Allerdings im englischen Sinne, nicht im offiziellen Sinne – Wikipedia ist keine offizielle Veröffentlichung für C oder Programmieren im Allgemeinen, und mir ist kein Amt oder eine maßgebliche Stelle bekannt, die den Begriff definiert.) Der C-Standard verwendet „verstecken“, also ist das vorzuziehen.

    – Eric Postpischil

    27. Juli 2018 um 1:07 Uhr


  • Schön, besonders mit dem Beispiel “gleiche Variable”. Allerdings denke ich “Der Code wird wie erwartet kompiliert und ausgeführt” wäre besser als “der Code wird kompiliert und ausgeführt als jemand, der es sorgfältig gelesen hat und alle Auswirkungen versteht erwartet” … wie Sie sagen, Code wie folgt “dürfte bei seinen Lesern noch mehr Verwirrung stiften” und das Problem ist ein verwirrter Leser erwarten von etwas anderes als das, was es tut.

    – TripeHound

    27. Juli 2018 um 9:54 Uhr

Du kannst. Aber Sie sollten sich der Tragweite bewusst sein is. wenn wir das Äußere nennen i mit i_1 und das Innere i mit i_2der Umfang der is lautet wie folgt:

for(int i = 0; i < 10; i++)
{
     // i means i_1
     for(int i = 0; i < 10; i++)
     {
        // i means i_2
     }
     // i means i_1
}

Sie sollten beachten, dass sie sich nicht gegenseitig beeinflussen und nur ihr Definitionsbereich unterschiedlich ist.

Das ist durchaus möglich, aber denken Sie daran, dass Sie es nicht ansprechen können
das erste deklarierte i

for(int i = 0; i < 10; i++)//I MEAN THE ONE HERE
{

  for(int i = 0; i < 10; i++)
    {

    }
}

in der zweiten Schleife innerhalb der zweiten untergeordneten Schleife

for(int i = 0; i < 10; i++)
{

  for(int i = 0; i < 10; i++)//the new i
    {
        // i cant see the i thats before this new i here
    }
}

Wenn Sie den Wert des ersten i anpassen oder abrufen müssen, verwenden Sie j in der zweiten Schleife

for(int i = 0; i < 10; i++)
{

  for(int j = 0; j < 10; j++)
    {

    }
}

und wenn Sie kreativ genug sind, können Sie beide in einer Schleife ausführen

for(int i ,j= 0; i < 10; (j>9) ? (i++,j=0) : 0 ,j++)
{
    printf("%d %d\n",i,j);
}

Benutzeravatar von HS
HS

Ja, Sie können den gleichen Zählervariablennamen für ein Inneres verwenden for Schleife wie für die äußere for Schleife.

Aus für Schleife:

for ( init_clause ; cond_expression ; iteration_expression ) loop_statement

Die Ausdrucksanweisung, die als verwendet wird loop_statement gründet sich selbst Blockbereich, der sich vom Bereich unterscheidet von init_clause.

for (int i = 0; ; ) {
    long i = 1;   // valid C, invalid C++
    // ...
}  

Der Umfang der loop_statement ist verschachtelt im Rahmen von init_clause.

Aus C Standards#6.8.5p5 Iterationsanweisungen [emphasis mine]

Eine Iterationsanweisung ist ein Block, dessen Geltungsbereich eine strikte Teilmenge des Geltungsbereichs seines einschließenden Blocks ist. Der Schleifenkörper ist auch ein Block, dessen Geltungsbereich eine strikte Teilmenge des Geltungsbereichs der Iterationsanweisung ist.

Aus C-Standards Nr. 6.2.1p4 Geltungsbereich von Bezeichnern [emphasis mine]

….Innerhalb des inneren Geltungsbereichs bezeichnet der Bezeichner die im inneren Geltungsbereich deklarierte Entität; das Die im äußeren Bereich deklarierte Entität ist ausgeblendet (und nicht sichtbar) innerhalb des inneren Bereichs.

Aus Sicht des Codes / Compilers wäre dies eine absolut gültige und legale Sache. Das int i im Inneren erklärt for(int i = 0; i < 10; i++) Schleife befindet sich in einem neuen und kleineren Gültigkeitsbereich, sodass die Deklaration Schatten die Erklärung von int i in der äußeren Schleife (oder anders gesagt: im inneren Bereich alle Zugriffe auf die Variable i gehe zum int i im inneren Geltungsbereich deklariert, wobei die int i im äußeren Bereich unberührt).

Aus Sicht der Codequalität ist dies jedoch absolut schrecklich. Es ist schwer zu lesen, schwer zu verstehen und leicht zu missverstehen. Tu es nicht.

Benutzeravatar von Safwan Shaikh
Safwan Scheich

Ja, Sie können es verwenden, aber es ist ziemlich verwirrend. Das Wichtigste ist der Geltungsbereich der lokalen Variablen innerhalb der Schleife. Soweit eine Variable innerhalb einer Funktion deklariert wird, ist der Gültigkeitsbereich dieser Variablen diese Funktion.

int a = 5;
// scope of a that has value 5
int func(){
    int a = 10;
   // scope of a that has value 10
}
// scope of a that has value 5

Ähnlich verhält es sich mit Schleifen, bei denen die innerhalb der inneren Schleife deklarierte Variable einen anderen Gültigkeitsbereich hat und die als äußere Schleife deklarierte Variable einen anderen Gültigkeitsbereich hat.

for(int i = 0; i < 10; i++){
    // In first iteration, value of i is 0

    for(int i = 1; i < 10; i++){
        // In first iteration, value of i is 1
    }
    // In first iteration, value of i is 0
}

Der bessere Ansatz besteht darin, unterschiedliche Variablen für innere und äußere Schleifen zu verwenden.

for(int i = 0; i < 10; i++){

    for(int j = 1; j < 10; j++){

    }

}

1421830cookie-checkKann eine ‘for’-Schleife innerhalb einer ‘for’-Schleife denselben Zählervariablennamen verwenden?

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

Privacy policy