goto und multiple labels mit gleichem Namen



  • Bitte keine Diskussion über die Sinnhaftigkeit von 'goto' losbrechen. Das Leben ist wie es ist und man kriegt manchmal Code aus dem Ausland der schrecklich ist.

    Ich vereinfache hier mal das Problem, auf das nötigste reduziert.

    #define Preambel DisableInterrupts(); \
      {
    
    #define Postambel UNLOCK: \
      EnableInterrupts(); \
      }
    
    void loggingFunctionText(const char* text)
    {
      Preambel
      if(!logging.Enabled())
        goto UNLOCK;
    
      // Your code here
    
      Postambel
    }
    
    void loggingFunctionInt(int value)
    {
      Preambel
      if(!logging.Enabled())
        goto UNLOCK;
    
      // Your code here
    
      Postambel
    }
    
    void BadFunction()
    {
      // code
      if(epicError)
        goto UNLOCK;
      // more code
    }
    

    Resultat ist:
    Eine Compile-Unit mit diveresen Labels gleichem Namens.

    Frage 1:
    Ist das grundsätzlich legitim?

    Frage 2:
    Wurden die geschweiften Klammern in den Macros eingeführt um das goto-Verhalten zu verbessern?

    Frage 3:
    Was springt die BadFunction an?



  • 1. Bis auf das Springen von einer Funktion in eine andere, ja. Labels müssen nur innerhalb einer Funktion eindeutig sein.

    2. Nein, sowohl Labels als auch goto scheren sich nicht um gewöhnliche lokale Scopes, sondern funktionieren auf Funktionsebene.

    3. Das dürfte eigentlich nicht kompilieren, afaik.



  • nurf schrieb:

    Frage 2:
    Wurden die geschweiften Klammern in den Macros eingeführt um das goto-Verhalten zu verbessern?

    Ne, ich vermute die sind da damit man nach Preambel gleich lokale Variablen definieren kann.



  • hustbaer schrieb:

    nurf schrieb:

    Frage 2:
    Wurden die geschweiften Klammern in den Macros eingeführt um das goto-Verhalten zu verbessern?

    Ne, ich vermute die sind da damit man nach Preambel gleich lokale Variablen definieren kann.

    ?
    Versteh ich nicht. 😞
    Ich tippe mal, dass die Klammern Compilerfehler provozieren sollen, wenn die POSTAMBEL fehlt...

    Ich hab gerade rumgespielt, wie ich sowas machen würde.

    #include <stdio.h>
    
    void lock(void) { puts("lock()"); }
    void unlock(void) { puts("unlock()"); }
    
    #define GUARDED	for(void (*cerb)(void)=lock; cerb; cerb=NULL, unlock()) for(;cerb?(*cerb)(),1:0;cerb=NULL)
    
    void func() {
    	GUARDED
    		puts("Hallo Welt!");
    }
    
    void funcyfunc() {
    	GUARDED {
    		if(1)
    			break; // oder continue - jedenfalls ohne goto
    		for(int i=0; i<10; ++i)
    			putchar('.');
    	}
    }
    
    int main() {
    	func();
    	funcyfunc();
    }
    

    So evtl.?

    Gibt's irgendein Pattern oder Feature dafür in modernem C?



  • das sieht ja grauenhaft aus. Was willst du eigentlich erreichen?



  • supertux schrieb:

    das sieht ja grauenhaft aus. Was willst du eigentlich erreichen?

    Offensichtlich sowas wie C++s D'tors.
    Und, supertux, Alternativen? Das war ja meine Frage. (und nebenbei bemerkt: ich bin nicht der OP)


  • Mod

    Furble Wurble schrieb:

    supertux schrieb:

    das sieht ja grauenhaft aus. Was willst du eigentlich erreichen?

    Offensichtlich sowas wie C++s D'tors.
    Und, supertux, Alternativen?

    C++?

    🙂



  • Furble Wurble schrieb:

    Und, supertux, Alternativen? Das war ja meine Frage. (und nebenbei bemerkt: ich bin nicht der OP)

    wie soll ich eine Alternative anbieten, wenn ich nicht einmal die Frage verstehe bzw. wenn es nicht klar ist, was der OP machen will 😕



  • supertux schrieb:

    Furble Wurble schrieb:

    Und, supertux, Alternativen? Das war ja meine Frage. (und nebenbei bemerkt: ich bin nicht der OP)

    wie soll ich eine Alternative anbieten, wenn ich nicht einmal die Frage verstehe bzw. wenn es nicht klar ist, was der OP machen will 😕

    Ich denke die Fragen des OP sind beantwortet.

    Mich hat dann nur interessiert, was Ihr so benutzt, um "exceptionsicheren" Code zu schreiben. Damit meine ich Techniken um sicherzustellen, dass malloc/free, fopen/fclose, DisableInterrupts/EnableInterrupts - oder in meinem Beispiel lock/unlock - immer paarweise aufgerufen werden. Egal welcher Ausführungspfad gewählt wird.

    Mein Guarded-Makro ist sicherlich "super clever"(™) - aber wahrscheinlich würde ich solche "cleveren" Lösungen zugunsten von sorgfältigen, herkömlichen Lösungen fallen lassen. Also ungefähr das auschreiben, was der Präprozessor aus dem Code vom Eingangsposting macht.



  • Makros sind Scheiße.

    C hat standandkonform für sowas nichts, weil C von Profis für Profis geschaffen wird und die wissen was sie tun.

    Gutes Programmdesign schützt bei solchen Fallen, setzt aber große Erfahrung voraus.
    Der Einsatz solcher Tools/Pattern/... u.dgl. kaschiert oft fehlerhaftes Programmdesign bzw. mangelnden Überblick und sollte sparsam verwendet werden, eben von Profis.

    gcc bietet als Erweiterung zum Standard z.B. cleanup+deprecated für solch ähnlich gelagerte Fälle:
    gcc: cleanup deprecated



  • Furbelle Wurbelle's Vorschlag sieht zwar ziemlich cool aus, aber wer soll das auf Anhieb verstehen?


Anmelden zum Antworten