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:
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
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.
@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.
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.
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
@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.
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.
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_tupper6bits0b11111100;
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_tswitches_front=status_front&SWITCHES_MASK;
3
uint8_tswitches_rear=status_rear&SWITCHES_MASK;
4
if(switches_front==switchesrear)
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 ;)
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.
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 ;-)
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.
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.
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.
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!)
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.