Frage zu Bitoperation!



  • Hallo,

    ich habe ein Problem mit einer Bitoperation und zwar folgendes in C++:

    ich will zwei Zahlen per Bitoperation miteinander verbinden
    idx ist ein int und col ein Farbwert
    #define COLANDIDX(idx, col) ((((DWORD) col) | (idx<<24)))

    Dann will ich aus dem Ergebnis des ersten Makros wieder mit den folgenden Makros den col Wert und den idx haben.
    #define IDXFROMCOL(colidx) (((DWORD) (colidx &= colidx)))
    #define COLFROMIDX(colidx) (colidx>>24)

    int ii = 10;
    COLORREF col = 657940;

    //Für erg erhalte ich 168430100
    DWORD erg = COLANDIDX(ii, col);
    //Für idx erhalte ich nun richtig wieder den Wert 10
    int idx = COLFROMIDX(erg);
    //Dieses Makro funktioniert nicht ich erhalte nicht wieder 657940
    COLORREF cc = IDXFROMCOL(erg);

    Kann mir jemand helfen IDXFROMCOL richtig zu definieren??



  • #define IDXFROMCOL(colidx) (((DWORD) (colidx & 0x00FFFFFF)))
    

    müsste funktionieren, aber warum nimmst du Makros und keine inline-Funktionen?



  • Danke das hat geholfen!



  • Nicht dass ich lästern wollte, aber das

    #define IDXFROMCOL(colidx) (((DWORD) (colidx & 0x00FFFFFF)))
    

    ist glatt gelogen, denn es extrahiert die Farbe, nicht den Index. Es sei denn, man versteht den Makronamen andersherum, als "Index entfernen und Farbe zurückgeben" statt "Index aus kombiniertem Wert extrahieren". Dann sollte man diese merkwürdige Denkweise allerdings als Kommentar dazuschreiben ...

    #define COLANDIDX((idx),(col)) ((DWORD)col | ((DWORD)((BYTE)idx) << 24))
    

    In einem 32bit System mag die Originalversion funktionieren, aber in einem 16bit System ist ein int auch nur 16bit breit und nach 24bit Schieben bleibt nichts mehr davon übrig. Also sollte man sicherheitshalber vor dem Schieben aus dem int auch ein DWORD machen. Und weil sowieso nur 8bit davon übrigbleiben, sollte man den Wert vorher auch auf 8bit ausgebremst haben.

    Bei Macro-Parametern sollte man sich übrigens zur Angewohnheit machen, alle Parameter grundsätzlich einzeln zu klammern. In diesem Fall ist's wurscht, aber bei berechneten Parametern, die im Macro wohlmöglich mehrfach verwendet werden, geht's sonst garantiert in die Hose. Wenn man immer klammert, kann man's nicht vergessen.

    #define IDXFROMCOL(colidx) (int)((colidx >> 24) & 0x000000FFUL) 
    #define COLFROMIDX(colidx) (colidx & 00FFFFFFUL)
    

    Wenn der Index schon als int reingesteckt wird, sollte er auch als int wieder rauskommen, um nicht unnötige Compiler-Warnungen zu provozieren. colidx auf DWORD zu casten, kann man sich dagegen getrost sparen. Wenn hier kein DWORD oder long reingesteckt wird, funktioniert sowieso nichts. Mit der Markierung der Bitmaske als unsigned long (nichts Anderes als DWORD) erspart man sich ggf. eine weitere Compiler-Warnung wegen signed/unsigned mismatch. OK, warning level 4 mag nicht jeder, aber auch der hat seine Existenzberechtigung. Schützt den Codierer vor der eigenen Schlamperei ...


Anmelden zum Antworten