Forum: PC-Programmierung Makros für Bitmanipulation


von Ralf (Gast)


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

von Rufus T. Firefly (Gast)


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.

von Chris (Gast)


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.

von Ralf (Gast)


Lesenswert?

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

von Lanius (Gast)


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 :)

von Chris (Gast)


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(...)).

von Lanius (Gast)


Lesenswert?

>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

von Lanius (Gast)


Lesenswert?

>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))

von Chris (Gast)


Lesenswert?

Dann stimmt der Name des Makros nicht. "bit" ist immer noch Singular.

von Werner B. (Gast)


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.

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
Noch kein Account? Hier anmelden.