WIe erstelle ich FLAGS?



  • Hi,

    wie kann man flags realisieren like this:

    meineFunktion (FLAG_EINS | FLAG_DREI | FLAG_SIEBEN);
    


  • das geht so:

    enum {
       EINS = 1;
       ZWEI = 1<<1;
       DREI = 1<<2;
       VIER = 1<<3;
    }
    

    willst du auch ne erklärung warum?



  • Naja, ich will mal erklären wieso.

    Davies Code-Schnipsel ist gleichwertig zu:

    enum { 
       EINS = 1; 
       ZWEI = 2; 
       DREI = 4; 
       VIER = 8; 
    }
    

    Bitverschiebung!

    Nun, diese 4 Werte der Aufzählung sind nun alle durch 2er Potenzen ausgedrückt. Genauer:
    EINS = 1 = 2 hoch 0
    ZWEI = 2 = 2 hoch 1
    DREI = 4 = 2 hoch 2
    VIER = 8 = 2 hoch 3

    was sich für weitere Werte fortsetzen liesse:
    FUENF = 16 = 2 hoch 4
    ...etc...

    Um nun das eigentliche Wesen der Flags zu verstehen, ist es wichtig, sich klar zu machen, wie diese 2er Potenzen intern im Rechner dargestellt werden. Wie du sicherlich weißt, kennt ein PC an sich nur einsen und nullen. Das bedeutet, er arbeitet nicht im dezimal, sondern im Binärsystem.
    Daher stellt er die Werte der Aufzählung (enum) intern folgendermaßen da:

    EINS = 1
    ZWEI = 10
    DREI = 100
    VIER = 1000

    Das bedeutet, jedes Bit (jede Stelle) ist einmalig mit einer Eins belegt.
    Der binäre oder (|) Operator verbindet nun diese Bits miteinander:
    Beispiele: EINS|DREI|VIER=1101
    ZWEI|VIER=1010
    EINS|ZWEI=0011

    Diese "verbundenen" Bits übergibst du nun beispielsweise an eine Funktion. Diese prüft dann wiederum, ob das jeweilige Bit tatsächlich gesetzt ist.
    Beispielsweise wird als Bitfolge 1100 an eine Funktion test übergeben. Diese prüft mit dem binären & Operator ob das letzte Bit gesetzt ist:

    bool test(int Bitfolge)
    {
        return (Bitfolge&8);
    }
    

    Dies liese sich natürlich mit jedem anderen Bit ebenso machen.

    Genauer vergleicht der & Operator jedes Bit seines ersten Arguments mit jedem Bit seines zweiten Arguments. Wenn beide Bits 1 sind, so ist das Ergebnis ebenfalls 1, ansonsten 0.

    Beim oberen Beispiel:
    Bitfolge: 1100
    Die Acht: 1000
    --------------
    1000

    was ungleich null ist, und die Funktion damit true zurück geben lässt.

    Hoffe konnte dir etwsa helfen.



  • ich hoffe, das steht nocht nicht bei den FAQs, wäre nämlich schade drum, diesen schönen Text hier verkommen zu lassen 😉



  • Hallo!

    Ich schreib meißtens

    #define EINS   0x00000001L
    #define ZWEI   0x00000002L
    #define DREI   0x00000004L
    #define VIER   0x00000008L
    #define FUENF  0x00000010L
    #define SECHS  0x00000020L
    #define SIEBEN 0x00000040L
    #define ACHT   0x00000080L
    

    Ist doch übersichtlicher, find ich 😃

    Wie wertet Ihr die Flags aus?
    Ich machs immer so. Gefält mir aber noch nicht. Geht doch sicher besser, oder? Bsp:

    void TestDlg::SetStatus(long FLAG)
    {
       BOOL x = FALSE;
    
       x = ((FLAG & EINS)  == EINS  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_1)->ShowWindow(x);
       x = ((FLAG & ZWEI)  == ZWEI  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_2)->ShowWindow(x);
       x = ((FLAG & DREI)  == DREI  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_3)->ShowWindow(x);
       x = ((FLAG & VIER)  == VIER  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_4)->ShowWindow(x);
       x = ((FLAG & FUENF) == FUENF ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_5)->ShowWindow(x);
       x = ((FLAG & SECHS) == SECHS ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_6)->ShowWindow(x);
       x = ((FLAG & SIEBEN)== SIEBEN) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_7)->ShowWindow(x);
       x = ((FLAG & ACHT)  == ACHT  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_8)->ShowWindow(x);
    }
    

    Und der Aufruf:

    SetStatus( EINS | ZWEI | DREI );
    

    Jetzt sind nur die ersten drei Buttons sichtbar.

    Bye, Sigi



  • naja legen wir loss

    void TestDlg::SetStatus(long FLAG)
    {
        GetDlgItem(IDC_BUTTON_1)->ShowWindow(FLAG & EINS);
        GetDlgItem(IDC_BUTTON_2)->ShowWindow(FLAG & ZWEI);
        GetDlgItem(IDC_BUTTON_3)->ShowWindow(FLAG & DREI);
        GetDlgItem(IDC_BUTTON_4)->ShowWindow(FLAG & VIER);
    }
    

    so kann man das machen oder wenn man weniger code redundanz will dann

    void TestDlg::SetStatus(long FLAG)
    {
        long button[] = { IDC_BUTTON_1, IDC_BUTTON_2, IDC_BUTTON_3, IDC_BUTTON_4 };
        long button_size = sizeof(button) / sizeof(button[0]);
    
        for(int i = 0, f = EINS; i < button_size; ++i, f <<= 1)
            GetDlgItem(button[i])->ShowWindow(FLAG & f);
    
    }
    


  • Hallo!

    Ich schreib meißtens

    #define EINS   0x00000001L
    #define ZWEI   0x00000002L
    #define DREI   0x00000004L
    #define VIER   0x00000008L
    #define FUENF  0x00000010L
    #define SECHS  0x00000020L
    #define SIEBEN 0x00000040L
    #define ACHT   0x00000080L
    

    Ist doch übersichtlicher, find ich 😃

    Für sowas verwenden nur alte Cler Makros. Versuchs mal mit Konstanten.

    Und ist ees übersichtlicher als:

    enum Flags {
       EINS   = 0x00000001L,
       ZWEI   = 0x00000002L,
       DREI   = 0x00000004L,
       VIER   = 0x00000008L,
       FUENF  = 0x00000010L,
       SECHS  = 0x00000020L,
       SIEBEN = 0x00000040L,
       ACHT   = 0x00000080L
    }
    

    Wie wertet Ihr die Flags aus?
    Ich machs immer so. Gefält mir aber noch nicht. Geht doch sicher besser, oder? Bsp:

    void TestDlg::SetStatus(long FLAG)
    {
       BOOL x = FALSE;
    
       x = ((FLAG & EINS)  == EINS  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_1)->ShowWindow(x);
       x = ((FLAG & ZWEI)  == ZWEI  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_2)->ShowWindow(x);
       x = ((FLAG & DREI)  == DREI  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_3)->ShowWindow(x);
       x = ((FLAG & VIER)  == VIER  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_4)->ShowWindow(x);
       x = ((FLAG & FUENF) == FUENF ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_5)->ShowWindow(x);
       x = ((FLAG & SECHS) == SECHS ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_6)->ShowWindow(x);
       x = ((FLAG & SIEBEN)== SIEBEN) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_7)->ShowWindow(x);
       x = ((FLAG & ACHT)  == ACHT  ) ? TRUE : FALSE; GetDlgItem(IDC_BUTTON_8)->ShowWindow(x);
    }
    

    Und der Aufruf:

    SetStatus( EINS | ZWEI | DREI );
    

    Jetzt sind nur die ersten drei Buttons sichtbar.

    Bye, Sigi

    BOOL, TRUE und FALSE sind auch uralter Mist. Verwende bool, true und false.

    und die bedingung gibt true oder false zurück. deshalb ist der ternäre Operator ?: überflüssig.

    Und ich müsste wissen, für was IDC_BUTTOM_... steht.vielleicht könnte mans dann in der Schleife machen.

    Sonst eben ausprogrammieren:

    void TestDlg::SetStatus(Flags flag)
    {
       GetDlgItem(IDC_BUTTON_1)->ShowWindow(flag & EINS);     
    
       GetDlgItem(IDC_BUTTON_2)->ShowWindow(flag & ZWEI);
    
       GetDlgItem(IDC_BUTTON_3)->ShowWindow(flag & DREI);
    
       ...
    }
    

    / edit: Na toll Dimah hat fast das gleiche geschreiben.



  • Danke Leute!

    Man lernt eben nie aus! 👍
    TSCHAU, SIGI


Anmelden zum Antworten