While-Verschachtelung streikt

T_55

Lieutenant
Registriert
Feb. 2013
Beiträge
638
Hallo ich hab gerade eine komische Sache:

Code:
int z = 0;
int a=0;
int b=0;
int c=0;

while(a<10)
{
   while(b<10)
   {
      while(c<10)
      {
         c++;
         z++;
      }
      b++;
   }
   a++;
}
std::cout << "ZÄHLER" << z << std::endl;

Und als Ergebnis bekommt man z = 10
z müsste doch 1000 (10*10*10) sein oder?

Gruß
 
Zuletzt bearbeitet:
Schau dir mal deine erste Zeile an
und deine innerste Schleife wird natürlich nur einmal durchlaufen, da c dann = 10 ist und damit die Schleifenbedinung nicht mehr True ergibt. Bei b =1 wird also schon nichts mehr gemacht
 
Zuletzt bearbeitet:
Absicht, dass ganz oben bei int z ein "=" fehlt?
 
Na die innerste Schleife ist nach 10 Durchgängen "dicht"
Und da z nur dort drin vorkommt ist da bei z=10 eben Schluss.
 
Hab ich nur falsch abgeschrieben, hätte der compiler auch nicht akzeptiert ;)
Ergänzung ()

Ach peinlich jetzt hab ich aber die Lösung. Die Variablen müssen direkt vor jeder Schleife = 0 definiert werden und nicht alle am Anfang :D Ich sollte ins Bett gehen ;)

So war es gewollt:

Code:
    int z = 0;
    int a=0;
    while(a<10)
    {
       int b=0;
       while(b<10)
       {
          int c=0;
          while(c<10)
          {
             c++;
             z++;
          }
          b++;
       }
       a++;
    }
    std::cout << "ZÄHLER" << z << std::endl;
 
du solltest trotzdem oben die variablen deklarieren..

int a=0;
int b=0;
int c=0;
int z=0;

und unten dann b=0; c=0; …
 
Mr.Smith schrieb:
du solltest trotzdem oben die variablen deklarieren..

int a=0;
int b=0;
int c=0;
int z=0;

und unten dann b=0; c=0; …

Hier nicht wirklich wichtig - aber prinzipiell gilt:
"So lokal wie möglich und so global wie nötig."
 
Stimmt. Ich denke der Tipp bezog sich auf die Performance. Außerhalb der Schleifen bedeutet hier: Weniger Allokationen. Kann also durchaus Sinn machen.
 
Zuletzt bearbeitet:
Jeder halbwegs normale Compiler wird da spätestens in der einfachsten Optimierungsstufe in beiden Fällen denselben Code ausspucken. Es ist ja nicht so, dass da Speicher vom Heap reserviert wird - in dem Fall würde ich zustimmen, Heap-Allokationen gilt es zu vermeiden bzw. so sinnvoll wie möglich weiterzuverwenden - im Normalfall wird hier überhaupt kein Speicher benutzt, sondern eines der Wegwerf-Register.

Wenn man sich über Mikro-Optimierungen unterhält, würde ich immer einen Blick auf den Compiler-Explorer werfen. Wenn man mal folgenden Code nimmt, um relativ wenige Optimierungstricks zuzulassen...
Code:
int test(int x) {
  int z = 0;
  int a = 0;
  while (a < x) {
    int b = 0;
    while (b < x) {
      int c = 0;
      while (c < x) {
        c += 1;
        z += 1;
      }
      b += 1;
    }
    a += 1;
  }
  return z;
}

...und die Optimierungen anschaltet (-O3), wird man feststellen, dass GCC relativ gute Schleifen erzeugt und Clang die Schleifen sogar ganz wegoptimiert und durch Multiplikationen ersetzt. Kurz: Compiler sind nicht so blöd, wie ihr denkt.

"So lokal wie möglich und so global wie nötig."
Dem stimme ich daher uneingeschränkt zu. Alles andere ist auch eine Fehlerquelle, wenn man nämlich - wie der TE - vergisst, die Variable jedes Mal neu zu initialisieren - wenn man sie gleich im richtigen Scope deklariert, wird man mehr oder weniger dazu gezwungen.
 
Zuletzt bearbeitet:
Kurze Anmerkung am Rande: Schleifen, die einfach n-mal durchlaufen werden sollen, lassen sich mit einer For-schleife in der Regel am elegantesten Programmieren. So würde das obige Beispiel mit For-Schleifen wie folgt aussehen:
Code:
for(int a=0; a<10; a++)
for(int b=0; b<10; b++)
for(int c=0; c<10; c++)
 z++
 
inter2k3 schrieb:
Hier nicht wirklich wichtig - aber prinzipiell gilt:
"So lokal wie möglich und so global wie nötig."

Kann man das so sagen? Gibt ja z.B. Variablen, die ich durchaus auch lokal machen könnte, aber aufgrund der häufigen Zugriffe sie lieber global mach und nicht jedes mal neu reinlese.
 
nitg schrieb:
Kann man das so sagen? Gibt ja z.B. Variablen, die ich durchaus auch lokal machen könnte, aber aufgrund der häufigen Zugriffe sie lieber global mach und nicht jedes mal neu reinlese.

Das sind dann natürlich Ausnahmen. Wenn das von inter2k3 genannte (und prinzipiell korrekte) Motto dazu führt, dass ich etwas rechenzeitintensives (oder anderweitig teures) unnötigerweise n mal tue, obwohl ich es eigentlich nur 1 mal erledigen müßte, dann ist das natürlich ein guter Grund, in diesem Fall von dem Motto abzuweichen.

P.S. Ich würde es nicht gleich global machen (dafür habe ich in meiner Karriere noch nie einen guten Grund gesehen), aber zumindest so viele Scopes nach außen verlegen, dass der erwünchte Ersparniseffekt eintritt.
 
Zuletzt bearbeitet:
nitg schrieb:
Kann man das so sagen? Gibt ja z.B. Variablen, die ich durchaus auch lokal machen könnte, aber aufgrund der häufigen Zugriffe sie lieber global mach und nicht jedes mal neu reinlese.
das kommt sicher auf den einzelfall an, und fuer das dafuer und das dagegen gibt es sicherlich reichhaltig valide gruende.
die idee hinter dem mantra ist, dass man
a) den speicherverbrauch (insb. stack) und
b) die menge der verwendeten variablen
in jedem block auf sein minimum reduzieren sollte. das gibt gewinne in performance sowie ueberblick.

ist die berechnung deiner variable, die du jetzt global machen willst, rechnerisch intensiv, dann spricht das stark fuer die notwendigkeit, sie global zu machen.
aendert sich hingegen der wert deiner variable je nach dem kontext, aus dem sie berechnet wird, dann ist eine einschraenkung des scopes erstrebenswert. gleiches gilt z.b. auch fuer multithreading-anwendungen, wo synchronisation von speicher (=variablen) ein grosses performanceoptimierungsproblem darstellt.
 
Zurück
Oben