Kurze Frage zu Makros



  • SeppJ schrieb:

    Ethon schrieb:

    Mach's halt so?

    Du kannst in Makros keine Makros ausführen.

    #define FOO #define BAR bar
    
    FOO
    BAR
    

    ➡

    #define BAR bar
    BAR
    

    du meinst bestimmt eher definieren und nicht ausführen.



  • Ich verstehe.

    Was ist dein Problem? Stört es dich so sehr, diese PP-Direktiven zu schreiben?

    Ich muss dich aber leider enttäuschen. Sowas wie du willst, gibt es nicht - SeppJ hat's schon gesagt. Makros sind Makros, man kann keine Makros in Makros definieren lassen.
    Daher kann man auch keine Abfolgen von Makros abkürzen.
    Das was am ehesten noch ginge, wäre...

    • Die Makros in einen Header zu packen.
    • Jedes mal vor dem kompilieren einen anderen Präprozessor, bspw. von dir geschrieben, drüberlaufen lassen, der bestimmte Ausdrücke ersetzt. Bei CodeBlocks bspw. kannste dir Pre/Post-Build Steps setzen und da so einen PP ablaufen lassen.

    Ist aber natürlich ein Aufwand für nix und wieder nix.

    ... denn es ist doch nun wirklich nicht so schlimm, einfach deine Direktiven aus zuschreiben.



  • Sone schrieb:

    Was ist dein Problem? Stört es dich so sehr, diese PP-Direktiven zu schreiben?

    Ach was, ich mach das natürlich nur zum Spaß ...

    Gerade folgende durchaus akzeptable Lösung gefunden

    http://stackoverflow.com/questions/7372448/c-macro-to-conditionally-compile-code



  • Kannst du den jeweiligen, plattformspezifischen Code nicht einfach in eine Funktion packen? Möglicherweise sogar mit der selben Signatur für jede Plattform? Dann könntest du, anstatt kompliziert mit bedingter Kompilierung zu arbeiten, z.B. einfach die Implementierung der Funktion für jede Plattform in eine separate .cpp Datei packen und einfach je nach Plattform die entsprechende .cpp Datei nehmen...



  • @Pria:

    Der Visual Studio Compiler kann auch folgendes

    #if defined(HALLO) && defined(WELT)
    #endif
    

    Aber auch mein Tip:
    * Versuche Makros durch inline Funktionen zu ersetzen
    * Nutze sonstige Präprozessor-Direktiven sparsam und weise

    Makros sind einfache Ersetzungssysteme. Der Präprozessor geht ersetzt den Makro Aufruf einfach stur steif und dies führt zu Fehlern die sich ganz einfach vermeiden lassen.

    #define min(A, B)   A < B ? A : B
    
    int main(int argc, char** argv)
    {
      int a = 5;
      int b = 6;
    
      min(++a, b++)+1;
    
      // wird zu 
      ++a < b++ ? ++a : b+++1;
    }
    


  • dot schrieb:

    Kannst du den jeweiligen, plattformspezifischen Code nicht einfach in eine Funktion packen? Möglicherweise sogar mit der selben Signatur für jede Plattform? Dann könntest du, anstatt kompliziert mit bedingter Kompilierung zu arbeiten, z.B. einfach die Implementierung der Funktion für jede Plattform in eine separate .cpp Datei packen und einfach je nach Plattform die entsprechende .cpp Datei nehmen...

    Das lohnt sich nicht wenn es sich dabei nur um kleine Abschnitte oder gar einzelne Funktionen handelt, etwa wenn der Endbenutzer eigenen Kontext hinzufügt. Dient auch nicht zuletzt der Lesbarkeit.

    Ich glaube ich bin mit dem if-replace durchaus zufrieden

    // Platform-Type als spezifische Definition im Projekt
    
    #ifdef Platform-Type_MyType //defined in a header
      #define PlatformName if(1)
    #else
      #define PlatformName if(0)
    #endif
    

    Und später im Code und auch

    int main(int argc, char** argv)
    {
      //do some stuff here
    
      //codeblock for my_sis
      my_sis
      {
         //do some mysis stuff here
      }
    
      //codeblock for my_sis with else
      my_sis
      {
         //do some mysis stuff here
      }
      else
        error_message
    
      //single statement for my_sis
      my_sis
         //do some mysis stuff here
    }
    

    Es kann mir keiner erzählen, dass das nicht übersichtlicher ist als ein block aus defines und gerade weil es sich dadurch nur um ein if replace handelt, kann ich innerhalb der klammern auch wieder defines setzen.

    Problem ist natürlich, dass das nicht ausserhalb fvon Funktionscode platziert werden kann



  • Das größte Problem ist dass soetwas nicht gut geht:

    WINDOWS_CODE
    {
        MessageBoxA(0, "Bla", ...);
    }
    

    Da zb. unter Linux der Compiler trotzdem auf den Inhalt das if-Blocks trifft (auch wenn der nicht erreichbar ist) und MessageBoxA nicht kennt.
    static if müsste es endlich mal geben...



  • müsste der compiler das nicht wegoptimieren?



  • xamarin schrieb:

    müsste der compiler das nicht wegoptimieren?

    Was?

    Es kann mir keiner erzählen, dass das nicht übersichtlicher ist als ein block aus defines

    Nö. Aber wie willst du das erreichen?



  • Pria schrieb:

    Es kann mir keiner erzählen, dass das nicht übersichtlicher ist als ein block aus defines

    Nö. Aber beides ist unglaublich häßlich im Vergleich zu plattformspezifisch implelentierten Inlinefunktionen mit über die Plattformen hinweg gleicher Schnittstelle.



  • // Wird nicht ausgeführt
    #define ANY_SYS_FLAG if (false)
    
    // Wird dann ausgeführt
    #undef ANY_SYS_FLAG
    
    //begin code block
    ANY_SYS_FLAG
    {
       //user-code here
    }
    //end of block
    


  • Pria schrieb:

    dot schrieb:

    Kannst du den jeweiligen, plattformspezifischen Code nicht einfach in eine Funktion packen? Möglicherweise sogar mit der selben Signatur für jede Plattform? Dann könntest du, anstatt kompliziert mit bedingter Kompilierung zu arbeiten, z.B. einfach die Implementierung der Funktion für jede Plattform in eine separate .cpp Datei packen und einfach je nach Plattform die entsprechende .cpp Datei nehmen...

    Das lohnt sich nicht wenn es sich dabei nur um kleine Abschnitte oder gar einzelne Funktionen handelt, etwa wenn der Endbenutzer eigenen Kontext hinzufügt. Dient auch nicht zuletzt der Lesbarkeit.

    Wenn du mich fragst lohnt sich das gerade dann, denn sobald es um mehr als ein paar vereinzelte, unzusammenhängende Funktionen geht, heißt es sowieso die entsprechende Funktionalität in einer eigenen Komponente (Modul, Library etc.) kapseln. Dieser ganze Makro Kram ist jedenfalls Mist wenn du mich fragst. Nicht nur weil es hässlich ist wie die Nacht finster, sondern vor allem auch, weil der Code dadurch meiner Erfahrung nach sehr schnell sehr anstregend wird... 😉



  • Wenn du mich fragst lohnt sich das gerade dann, denn sobald es um mehr als ein paar vereinzelte, unzusammenhängende Funktionen geht, heißt es sowieso die entsprechende Funktionalität in einer eigenen Komponente (Modul, Library etc.) kapseln. Dieser ganze Makro Kram ist jedenfalls Mist wenn du mich fragst. Nicht nur weil es hässlich ist wie die Nacht finster, sondern vor allem auch, weil der Code dadurch meiner Erfahrung nach sehr schnell sehr anstregend wird... 😉

    Jup sehe ich genauso.

    Ich bin kein Freund von #if Kaskaden. Die Größe deiner main() Funktion ist proportional zu der (Anzahl der Codezeilen pro Implementierung) mal Anzahl der Implementierungen. Wenn da ein Fehler in der Implementierung ist, wird das Debugging spaßig 😞

    @Pria :
    Jetzt mal bitte weg von der Implementierung: Kann es dass du eine Schnittstelle, mit verschiedene Implementierungen hast, welche ja nach Lage eingesetzt werden? Wenn ja, dann definiere doch deine Schnittstelle und biete die verschiedene Implementierungen hierfür in verschiedenen Modulen (DLL's, Remote Procedure Calls,...) an. Als Ideengeber eignen sich hierfür die Design Patterns (Broker Pattern, Client-Server Architektur,...).



  • xamarin schrieb:

    müsste der compiler das nicht wegoptimieren?

    Natürlich wird es wegoptimiert. Allerdings kommt der Schritt, bei dem er erstmal versucht den Code zu verstehen, logischerweise bevor etwas wegoptimiert wird. Und da würgt er eben über nicht deklarierte Funktionen etc.


Anmelden zum Antworten