Forum: Mikrocontroller und Digitale Elektronik 6 Bits eines Bytes in if-Abfrage vergleichen / AtmelStudio


von R. F. (inet_surfer88)


Lesenswert?

Hallo zusammen,

ich programmiere mit dem Atmel Studio und möchte folgendes machen:

Ich habe zwei 8-Bit-Werte, Wert A und Wert B

in einer if-Abfrage mochte ich die beiden Werte auf Gleichheit prüfen, 
aber nur die unteren 6 Bits. Die oberen beiden Bits sollen aus dem 
Vergleich ausgeschlossen werden, aber dürfen nicht verändert werden.

Eine Möglichkeit wäre 2 Hilfsvariablen, etwa so:
1
temp_a=wert_a&0b00111111; temp_b=wert_b&0b00111111;
2
3
if (temp_a==temp_b)


Geht das auch etwas eleganter, evtl. ohne die beiden Hilfsvariablen?


Ich habe schon folgendes versucht:
1
if ((wert_a&=0b00111111)==(wert_b&=0b00111111))

Allerdings funktioniert das nicht, da hier zwar der Vergleich korrekt 
ausgeführt wird, aber hinterher die beiden Werte wert_a und wert_b 
verändert wurden (jeweils die beiden oberen Bits gelöscht).


Gibt es hier eine bessere Lösung als die Variante mit den beiden 
Hilfswerten?


Gruß Rüdiger

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

R. F. schrieb:
> Gibt es hier eine bessere Lösung als die Variante mit den beiden
> Hilfswerten?

Ja klar.

„a &= b;“ ist ja die Kurzform für „a = a & b;“, d. h. die Neuzuweisung
an „a“ ist bei diesem Operator implizit.  Lass sie doch einfach weg,
in deiner ersten Form hattest du doch auch ein einfaches „&“ stehen.

Binäre Konstanten mit 0bxxx sind übrigens eine GCC-Erweiterung und
(leider) nicht portabel.

von Falk B. (falk)


Lesenswert?

@R. F. (inet_surfer88)

>Geht das auch etwas eleganter, evtl. ohne die beiden Hilfsvariablen?

Sicher.


>Ich habe schon folgendes versucht:

>if ((wert_a&=0b00111111)==(wert_b&=0b00111111))

Falsch. Du willst vergleichen, nicht zuweisen.

1
if ((wert_a & 0b00111111) == (wert_b & 0b00111111)) {
2
  // mach was
3
}
4
5
// normale Bitmasken, die jeder Compiler versteht
6
if ((wert_a & 0x3F) == (wert_b & 0x3F)) {
7
  // mach was
8
}

Die Zwischenwerte berechnet der Compiler in "unsichtbaren" 
Hilfsvariablen.

>Gibt es hier eine bessere Lösung als die Variante mit den beiden
>Hilfswerten?

Ein C-Buch lesen, durcharbeiten und, so Gott will, verstehen.

von Cosinus (Gast)


Lesenswert?

oder:

if((werta ^ wertb)&0b00111111)==0b00111111)

von Hannäs (Gast)


Lesenswert?

Cosinus schrieb:
> if((werta ^ wertb)&0b00111111)==0b00111111)

Nicht richtig. Eher:

If((werta ^ wertb)&0b00111111)==0)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Cosinus schrieb:
> oder:
>
> if((werta ^ wertb)&0b00111111)==0b00111111)

Hannäs schrieb:
> Nicht richtig. Eher:

Es ist OK, sich mit sowas beim IOCCC zu beteiligen.

Aber einem Fragesteller, der offensichtliche Schwierigkeiten hat,
die Bits dort überhaupt auseinanderzuhalten, braucht man sowas nun
wirklich nicht zu empfehlen.

von R. F. (inet_surfer88)


Lesenswert?

Hallo zusammen,

Falk B. schrieb:

> if ((wert_a & 0b00111111) == (wert_b & 0b00111111)) {
>   // mach was
> }

Oh, mann, da bin ich aber gehörig auf dem Schlauch gestanden! Darf ich 
die Frage hiermit zurückziehen??


> Ein C-Buch lesen, durcharbeiten und, so Gott will, verstehen.
Hab ich schon gemacht, ganz ehrlich. Ist aber schon eine Weile her und 
so oft programmiere ich jetzt halt nicht.


Danke an alle und Gruß
Rüdiger

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Man könnte auch nen bitshift nach links durchführen. Geht das von der 
Ausführung her schneller?

von Falk B. (falk)


Lesenswert?

@Reginald Leonczuk (Firma: HS Ulm) (reggie)

>Man könnte auch nen bitshift nach links durchführen. Geht das von der
>Ausführung her schneller?

Nicht auf dem AVR.

von Samstag (Gast)


Lesenswert?

Falk B. schrieb:
> @Reginald Leonczuk (Firma: HS Ulm) (reggie)
>
> Man könnte auch nen bitshift nach links durchführen. Geht das von der
>>Ausführung her schneller?
>
> Nicht auf dem AVR.

Geht es um AVR? Mit dem Studio kann man auch ARM befeuern.

von Cosinus (Gast)


Lesenswert?

Hannäs schrieb:
> Nicht richtig. Eher:
>
> If((werta ^ wertb)&0b00111111)==0)

Exakt, ist mir auch noch eingefallen.

von R. F. (inet_surfer88)


Lesenswert?

Hallo,

Samstag schrieb:
> Geht es um AVR? Mit dem Studio kann man auch ARM befeuern.

ATMEGA644P

von Tom (Gast)


Lesenswert?

Wenn man sicherstellen und deutlich machen möchte, dass beide Variablen 
mit der gleichen Bitmaske verundet werden, darf man die Bitmaske auch in 
eine Zwischenvariable, ein #define o.ä. stecken.

Binär angegebene Zahlen mit 0b sind so unübersichtlich, dass man erst 
nach langer Fehlersuche merkt, dass man bei der 17. Programmänderung nur 
in einer der Konstanten eine Stelle geändert hat.
1
if ((wert_a & 0b11111100) == (wert_b & 0b1111100))
Fehler sofort gesehen?

1
#define ALL_LED_PINS 0b11111100
2
if ((wert_a & ALL_LED_PINS) == (wert_b & ALL_LED_PINS))
3
4
//-----------
5
6
uint8_t upper6bits 0b11111100;
7
if ((wert_a & upper6bits) == (wert_b & upper6bits))

Auch die Zwischenvariablen können je nach Situation sinnvoll sein:
1
/* bits 2..7 enthalten den Zustand der Schalter */
2
uint8_t switches_front = status_front & SWITCHES_MASK;
3
uint8_t switches_rear = status_rear & SWITCHES_MASK;
4
if (switches_front == switches rear)
Die zwei überflüssigen Zeilen optimiert der Compiler wahrscheinlich weg. 
Dafür ist die Chance höher, nach 3 Monaten Pause sofort zu verstehen, 
was man sich damals beim Schreiben gedacht hat.

In größeren Projekten macht man sich mit den vorgeschlagenen "eleganten" 
XOR-Einzeilern bei den Kollegen, die das warten dürfen, höchst 
unbeliebt. Als Hobyist darf und soll man aber mit unnötiger Komplexität 
an der Verständnisgrenze Spaß haben ;)

von Fritz (Gast)


Lesenswert?

Tom schrieb:
> in einer der Konstanten eine Stelle geändert hat.if ((wert_a &
> 0b11111100) == (wert_b & 0b1111100))
> Fehler sofort gesehen?
>
> #define ALL_LED_PINS 0b11111100

genau deswegen würde ich aber eine hexadezimale Schreibweise vorziehen
#define ALL_LED_PINS 0xfc

oder für dezimal-fans  :-)
#define ALL_LED_PINS (255-3)

Abzählen der bit-positionen in Binärwerten ist doch sehr fehleranfällig!
8-bit gehen ja noch aber ab 16-bit wird es schon sehr grenzwertig.

Tom schrieb:
> Die zwei überflüssigen Zeilen optimiert der Compiler wahrscheinlich weg.
> Dafür ist die Chance höher, nach 3 Monaten Pause sofort zu verstehen,
> was man sich damals beim Schreiben gedacht hat.
>
> In größeren Projekten macht man sich mit den vorgeschlagenen "eleganten"
> XOR-Einzeilern bei den Kollegen, die das warten dürfen, höchst
> unbeliebt. Als Hobyist darf und soll man aber mit unnötiger Komplexität
> an der Verständnisgrenze Spaß haben ;)

Ein Wort zum Optimieren
Der Compiler mag das zwar wegoptimieren wenn man entsprechende Schalter 
setzt. Das hat aber den Nachteil, dass das Debugging schwieriger wird, 
weil der Code nicht direkt umgesetzt wird und z.B. Single-stepping nicht 
mehr so leicht nachvollziehbar ist (wie Du gemeint hast speziell von 
nachbetreuenden Kollegen).
Für jedem Embedded-Programmierer (egal ob Hobby oder Beruf) sollten aber 
die Begriffe signed unsigned binär decimal hexadecimal and or xor ... 
genauso klar und verständlich sein wie das kleine 1*1 für einen 
Volksschüler!
Wo liegt bei Dir die unnötige Komplexität?
Im Definieren 2er Zwischenvariablen, die nur weiter unnötige Namen 
einführt.
oder
Im XOR-Einzeiler, den jeder halbwegs sattelfeste Programmierer auf 
Anhieb versteht.

von Wolfgang (Gast)


Lesenswert?

Jörg W. schrieb:
> Es ist OK, sich mit sowas beim IOCCC zu beteiligen.
>
> Aber einem Fragesteller, der offensichtliche Schwierigkeiten hat,
> die Bits dort überhaupt auseinanderzuhalten, braucht man sowas nun
> wirklich nicht zu empfehlen.

So schlimm ist die Formulierung doch nun wirklich nicht.
Elementare Logikfunktionen wie bitweises Und/Oder/Exor sollte man 
vielleicht nicht als Geheimwissenschaft handeln ;-)

von Markus (Gast)


Lesenswert?

Tom schrieb:
> In größeren Projekten macht man sich mit den vorgeschlagenen "eleganten"
> XOR-Einzeilern bei den Kollegen, die das warten dürfen, höchst
> unbeliebt. Als Hobyist darf und soll man aber mit unnötiger Komplexität
> an der Verständnisgrenze Spaß haben ;)
Sowas läßt sich einfach in einer Funktion/Methode verstecken, gerne 
inline, und mit einem Unittest verproben und absichern.
Später dann, wenn man mal wieder drüber stolpert, interessiert einem 
eher nur mehr, daß da eine Entscheidung getroffen und was da 
entschieden wird, aber nicht mehr, wie das im Detail umgesetzt ist. 
Ansonsten würde man sich mehr und mehr in Details verlieren.

von Tom (Gast)


Lesenswert?

Fritz schrieb:
> [...]
War das Satire?

von Fritz (Gast)


Lesenswert?

Tom schrieb:
> Fritz schrieb:
>> [...]
> War das Satire?

Nein ist als "usw." zu verstehen, da ich ja nur die einfachsten 
Logikfunktionen angeführt habe.

Satire war damit nicht gemeint. Fehlt mir dazu wahrscheinlich die 
Fantasie.

von Wolfgang (Gast)


Lesenswert?

Markus schrieb:
> Später dann, wenn man mal wieder drüber stolpert, interessiert einem
> eher nur mehr, daß da eine Entscheidung getroffen und was da
> entschieden wird, aber nicht mehr, wie das im Detail umgesetzt ist.

Stimmt. In manch moderner Software werden nur nach Komponenten 
zusammengeklickt, die irgendetwas machen und keiner schert sich mehr um 
den Overhead. Ein Programm, das die Funktionalität früher in ein 
paarhundert kB enthalten hätte, mutiert dann zu einer 100MB App.

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Fritz schrieb:
> Satire war damit nicht gemeint. Fehlt mir dazu wahrscheinlich die
> Fantasie.

Für Satire ist nicht Fantasie, sondern Intelligenz die Vorraussetzung ;) 
(absolut nicht angreifend gemeint!)

von Markus L. (rollerblade)


Lesenswert?

Wolfgang schrieb:
> In manch moderner Software werden nur nach Komponenten
> zusammengeklickt, die irgendetwas machen und keiner schert sich mehr um
> den Overhead.
Übertreibt mal nicht so maßlos. Welcher Overhead genau entsteht denn bei 
einer inline deklarierten Funktion oder einer Funktion, die der Compiler 
eh wegoptimiert? Makros gäb's für eine derartige Frickelei auch noch.

Dir ist unstrukturierter und dadurch hochdetailreicher Code lieber, den 
Du bei jeder späteren Änderung wieder analysieren musst, um zu 
verstehen, was da abgeht, damit Du überhaupt was daran ändern kannst? 
Und Du kommentierst Dir lieber einen Wolf, anstatt den Code entsprechend 
der Problemstellung sauber zu strukturieren und den Bezeichnern 
sprechende Namen zu geben, so daß es so gut wie keiner Kommentare mehr 
bedarf?

Funktionen/Methoden sind nicht nur zum Wiederverwenden da. Die können 
auch Details wegkapseln, die keiner beim Caller sehen will. Warum? Weil 
diese Details nicht hilfreich sind, um zu verstehen, was der Caller 
macht. Das nennt man strukturierte Programmierung und macht man seit 50 
Jahren so.

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.