Komische Verschachtelung von switch und for



  • Hallo,

    ich bin heute bei einem Programm auf etwas Komisches gestoßen: Hier befindet sich eine Switch-Verzweigung und eine For-Schleife. Diese sind jedoch total seltsam verschachtelt. Der Code ließ sich einwandfrei mit dem GCC kompilieren. Jedoch sieht das alles etwas seltsam aus. Sieht der C89-Standard so etwas vor? Ich habe gelesen, dass man niemals ein goto in eine For-Schleife machen sollte, da das Verhalten undefiniert sein. Doch wie sieht es mit diesem seltsamen case aus?

    unsigned
    getRandom (unsigned from, unsigned to)
    {
      int static seed;
      switch (seed)
        {
        case 0:
          seed = (unsigned) time ();
          for (;;)
    	{
    	  return (seed % (to - from + 1) + from);
        default:
    	  seed ^= seed << 23;
    	  seed ^= seed >> 13;
    	  seed ^= seed << 29;
    	}
        }
    }
    
    main ()
    {
      unsigned number = 0;
      int i = 100;
      while (i--)
        {
          number = getRandom (0, 100);
          printf ("%u\n", number);
        }
    }
    

  • Mod

    Viele Schleifen haben eine Variable, die im Schleifenkopf initiliasiert und dann getestet wird. Ein goto in eine solche Schleife hinein würde die Initialisierung überspringen, der folgende Zugriff auf diese Variable wäre dann im Allg. undefiniert.
    Im konkreten Fall wird allerdings keine solche Initilialisierung übersprungen, das ist also eine Art dynamische Initialisierung der statischen Variablen seed (für arme Leute, die sich keinen C++-Compiler leisten können 😉


  • Mod

    Die Formulierung des switch-Konstrukts im Sprachstandard ist recht lax. Für ein weiteres solches Konstrukt und Erklärung, warum das erlaubt ist:
    Google: Duff's device



  • Vielen Dank für die schnelle Antwort. Aber warum hat man nicht direkt geschrieben:

    unsigned
    getRandom (unsigned from, unsigned to)
    {
      int static seed;
    
      if (seed == 0)
        {
          seed = (unsigned) time ();
        }
      else
        {
          seed ^= seed << 23;
          seed ^= seed >> 13;
          seed ^= seed << 29;
        }
      return (seed % (to - from + 1) + from);
    }
    


  • Höchstwahrscheinlich aus Performancegründen, aber ob das heutzutage noch valid ist? Ich kann es mir kaum vorstellen...

    MfG SideWinder



  • Das sieht fast wie das Ergebnis von einem Discompiler aus, der auf goto verzichtet.

    Das compilierte Ergebnis vom original Post und Variante 2 sollte bei optimierter Compilierung gleich sein.
    Der Compiler benutzt für seinen Code durchaus "goto" (bzw. jmp).


Anmelden zum Antworten