www.mikrocontroller.net

Forum: PC-Programmierung Makros für Bitmanipulation


Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lanius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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(...)).

Autor: Lanius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lanius (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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))

Autor: Chris (Gast)
Datum:

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

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.