Makros für Bitmanipulation

Gast #201139
Lesenswert?

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
Gast #201140
Lesenswert?

.

  "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.
Gast #201141
Lesenswert?

#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.
Gast #201143
Lesenswert?

#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 :)
Gast #201144
Lesenswert?

> #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(...)).
Gast #201148
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren