Hallo, ich versuche, Makros für Bitmanipulationen zu erstellen. Ich arbeite mit dem C51 Compiler von Keil (Demo). Folgende Makros habe ich geschrieben: //Makros für CHAR-Variablen #define GETBIT(ucByte, ucBit) ((ucByte & ucBit) > 0 ? 1 : 0) #define CLRBIT(ucByte, ucBit) (ucByte &= ~ucBit) #define SETBIT(ucByte, ucBit) (ucByte |= ucBit) #define INVBIT(ucByte, ucBit) (GETBIT(ucByte, ucBit) == 1 ? CLRBIT(ucByte, ucBit) : SETBIT(ucByte, ucBit)) #define MODBIT(ucByte, ucBit, ucBitStatus) (ucBitStatus > 0 ? SETBIT(ucByte, ucBit) : CLRBIT(ucByte, ucBit)) Die Namen der Makros sind, hoffe ich, selbst erklärend. ucBit ist immer ein Wert 2 hoch n, wobei n die Nummer des gewünschten Bits ist. Realisiert habe ich dies durch Bitmasken, also Bit0 = B00000001, Bit1 = B00000010, Bit2 = B00000100, usw. Das Problem ist, das sie leider noch nicht richtig funktionieren. Das äussert sich z.B. dadurch, dass einige der Makros offenbar in der Lage sind, eine Variable zu ändern, die gar nicht als Parameter übergeben wurde. Die fälschlicherweise geänderte Variable liegt direkt neben der zu manipulierenden im Speicher. Meine Vermutung ist, dass eventuell ein Type-Cast notwendig ist --> Kann es sein, dass Makros mit INT-Werten arbeiten?!? Kann sie bitte mal jemand überprüfen? Oder vielleicht hat jemand fertige Makros, die funktionieren? Makros für INT und LONG sind auch willkommen! Bräuchte halt alle genannten Funktionen, also Setzen, Löschen, Invertieren, Abfragen und Modifizieren (= übergebenen Bit-Wert zuweisen, siehe MODBIT). Falls mir jemand funktionsfähige Makros zur Verfügung stellen kann, wäre ich dankbar. Möchte allerdings trotzdem wissen, warum meine Makros nicht tun, sonst ist ja nix gelernt grins Danke Gruß Ralf
. "Meine Vermutung ist, dass eventuell ein Type-Cast notwendig ist --> Kann es sein, dass Makros mit INT-Werten arbeiten?!?" Macros "arbeiten" überhaupt nicht mit irgendwelchen Datentypen. Sie sind nur ein Textersatzmechanismus des Präprozessors - Du solltest also Deine Macros durch manuellen Textersatz auch selbst testen können.
#define GETBIT(ucByte, ucBit) ((ucByte & ucBit) > 0 ? 1 : 0) Das würde ich (primär aus Gründen der Lesbarkeit) ändern. Lass diesen if-operator ?: komplett weg, er bringt in dem Fall genau gar nichts, da eh keine negativen Werte auftreten können. Hintergrund: In C gilt die Regel, dass jede (ganze) Zahl implizit in einen bool-Wert konvertiert werden kann (also wahr oder falsch, "bool" selbst gibts ja erst bei C99). Dabei wird jede Zahl ungleich 0 als wahr aufgefasst; d.h. die Befehle while(1);, while(2); und while(-100); bewirken genau das gleiche, nämlich jeweils eine Endlosschleife. Dein :?-Konstrukt ist in etwa vergleichbar mit folgender genialen Konstruktion (die man leider manchmal immer noch sehen muss): if(x) return true; else return false; ...wer so etwas schreibt (das machst du ja zum Glück nicht) zeigt, dass er if-Abfragen und Aussagen nicht wirklich verstanden hat.
Hi Chris, Ja, ich verstehe, was du mit dem if-Beispiel meinst. Ich kann ja gleich den Wert von x zurückgeben. Werde das GETBIT-Makro entsprechend umbauen. Gruß Ralf
#define setBit(x,y) ((x) |= (y)) #define clearBit(x,y) ((x) &= ~(y)) #define toggleBit(x,y) ((x) ^= (y)) #define bitIsSet(x,y) (((x) & (y))==(y)) #define bitIsClear(x,y) (((x) & (y))!=(y)) Klammern dienen der Sicherheit. Übersetzt man mit -E als Parameter (GCC) kann man sich auch ansehen was die Textverarbeitung daraus macht. Vorsicht bei Sachen wie: if(bitIsSet(a,b++)) daraus wird: (((a) & (b++))==(b++)) und du hast einen tollen Bug :)
> #define bitIsSet(x,y) (((x) & (y))==(y))
Auch du kannst dir hier das ==(y) sparen.
Für bitIsClear würd ich kein eigenes Makro schreiben, das schreibt man
viel schneller und genauso lesbar als if(!bitIsSet(...)).
>Auch du kannst dir hier das ==(y) sparen.
uups, stimmt :)
dadurch besteht die Gefahr von doppelt veränderten Variablen auch nicht
mehr (y++), danke für den Tip
>Auch du kannst dir hier das ==(y) sparen.
Stimmt doch nicht!
Ich verwende den Macro auch um mehre Bits auf einmal abzufragen.
z.B.
if(bitIsSet(PORT1,TASTE1 | TASTE2))
Dann stimmt der Name des Makros nicht. "bit" ist immer noch Singular.
Das Problem im Hintergrund ist... in 99% aller Fälle findet man ein Makro das so aussieht #define TRUE (1) #define FALE (0) Dabei ist aber erste Teil (das TRUE) eigentlich falsch ;-) Es müsste eigentlich heissen #define FALSE (0) #define TRUE (!FALSE) denn alles was nicht explizit FALSE (sprich NULL) ist, ist TRUE.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.