Bit in einem Byte lesen bzw. schreiben
-
Ne Union voller #define ? es gibt Bitfelder in ANSI-C, kanns ja mal googeln.
Ansonsten geht es so11110111=247 kram den Windows-Rechner aus Zubehör raus und ermittle die Dezimalzahl
mit and (&) kannst du einzelne oder mehrere Bits löschen - hier das 4. z.B. var &= 247;
mit and kannst du testen, ob ein Bit gesetzt ist z.B. if (var == 247) true Bit gesetzt00001000=8
mit or (|) kannste einzelne Bits setzen - hier das 4 z.B. var |= 8; 4. Bit wurde gesetztvar &= 0; alle Bits löschen
var |= 0xff; alle Bits setzen
-
groovemaster schrieb:
net schrieb:
das ergibt doch kein bool (1 oder 0), sondern 4 oder 0
Der Ausruck mit dem bitweisen UND schon.
kommt drauf an mit was du 'undest'...
groovemaster schrieb:
...Aber if erwartet einen boolschen Ausdruck, deshalb wird das Ergebnis implizit nach bool (bzw. 0 oder 1) konvertiert. Da ich noch
!= 0x00
geschrieben habe, liegt ein solcher boolscher Wert bereits vor, und es muss nichts mehr konvertiert werden.
dem 'if' ist das ziemlich egal ob man '!=0' einbaut oder nicht. das entscheidet selber ob 0 oder nicht-0. es muss auch nix konvertieren, etwa von 'int' nach 'bool' oder '_Bool'. wieso auch?
-
net schrieb:
kommt drauf an mit was du 'undest'...
Was kommt drauf an?
net schrieb:
dem 'if' ist das ziemlich egal ob man '!=0' einbaut oder nicht.
Schon klar. Deshalb schreib ich es aber auch nicht, sondern um den Code verständlicher zu machen.
net schrieb:
das entscheidet selber ob 0 oder nicht-0. es muss auch nix konvertieren, etwa von 'int' nach 'bool' oder '_Bool'. wieso auch?
Das habe ich auch nicht geschrieben. Lies richtig! Ich sprach von "boolschem Ausdruck", das kann in C ==0 und !=0 sein, in C++ false und true, in VB False und True und in einer anderen Sprache etwas ganz anderes. Das ist auch nicht sprachabhängig, sondern einfach Logik. Damit war nicht ein Typ bool oder _Bool oder was auch immer gemeint. Und bis der Compiler soweit ist, muss er eine Umwandlung durchführen. Von mir aus kannst du diese "Umwandlung" auch einfach nur "Vergleich auf 0" nennen, ist letztendlich gehüpft wie gesprungen. Tatsache ist aber, dass ein weiterer Schritt notwendig ist, mit !=0 jedoch nicht, da bereits ein verwertbares Ergebnis vorliegt. Mit 0 und 4 alleine kann if jedenfalls nicht entscheiden, ob nun der if oder else Zweig angesprungen werden soll.
-
groovemaster schrieb:
Von mir aus kannst du diese "Umwandlung" auch einfach nur "Vergleich auf 0" nennen...
genau. mehr ist das nicht.
groovemaster schrieb:
Tatsache ist aber, dass ein weiterer Schritt notwendig ist, mit !=0 jedoch nicht, da bereits ein verwertbares Ergebnis vorliegt. Mit 0 und 4 alleine kann if jedenfalls nicht entscheiden, ob nun der if oder else Zweig angesprungen werden soll.
doch. 0 oder nicht-0 reichen. der zusätzliche vergleich '!=0' im code ist völlig überflüssig, da er sowieso gemacht wird. kleines beispiel (msvc6):
void test_if (int x) { if (x & 4) _asm nop; if ((x & 4) != 0) _asm nop; }
ergibt:
.... 277: if (x & 4) 00401038 mov eax,dword ptr [ebp+8] 0040103B and eax,4 0040103E test eax,eax 00401040 je test_if+23h (00401043) 278: _asm nop; 00401042 nop 279: if ((x & 4) != 0) 00401043 mov ecx,dword ptr [ebp+8] 00401046 and ecx,4 00401049 test ecx,ecx 0040104B je test_if+2Eh (0040104e) 280: _asm nop; 0040104D nop ....
-
net schrieb:
doch. 0 oder nicht-0 reichen. der zusätzliche vergleich '!=0' im code ist völlig überflüssig, da er sowieso gemacht wird.
Du widersprichst dir selbst. Reicht 0 und 4 nun aus, oder ist noch ein Vergleich notwendig? Btw, worum geht es hier überhaupt? Dass != 0 nicht dastehen muss, ist doch schon lange geklärt. Ich mach das, weil es einfach zum besseren Codeverständnis beiträgt. Ob explizit oder implizit ist letztendlich egal.
-
groovemaster schrieb:
Btw, worum geht es hier überhaupt?
um solche sätze z.b:
groovemaster schrieb:
Mit 0 und 4 alleine kann if jedenfalls nicht entscheiden, ob nun der if oder else Zweig angesprungen werden soll.
womit du meinst: if macht intern aus 0 'falsch' und aus nicht-0 'wahr'
was sich aber liest wie: if(0) oder if(4) funktionieren nicht als vergleich
-
Autsch!
Da habe ich doch die wichtigsten Zeilen unterschlagen:
struct bit_def { char b0:1; char b1:1; char b2:1; char b3:1; char b4:1; char b5:1; char b6:1; char b7:1; }; union byte_def{ struct bit_def bit; char byte; }; union byte_def p0_addr; #define p0 p0_addr.byte #define p0_0 p0_addr.bit.b0 /* Port P0 bit0 */ #define p0_1 p0_addr.bit.b1 /* Port P0 bit1 */ #define p0_2 p0_addr.bit.b2 /* Port P0 bit2 */ #define p0_3 p0_addr.bit.b3 /* Port P0 bit3 */ #define p0_4 p0_addr.bit.b4 /* Port P0 bit4 */ #define p0_5 p0_addr.bit.b5 /* Port P0 bit5 */ #define p0_6 p0_addr.bit.b6 /* Port P0 bit6 */ #define p0_7 p0_addr.bit.b7 /* Port P0 bit7 */
Jetzt macht's Sinn
.
-
net schrieb:
um solche sätze z.b:
Nein, ich meinte, worum es bei deinem ersten Beitrag ging.
net schrieb:
womit du meinst: if macht intern aus 0 'falsch' und aus nicht-0 'wahr'
was sich aber liest wie: if(0) oder if(4) funktionieren nicht als vergleichEs ging hier aber nicht um den high-level Aspekt, sondern um semantische Details. Wenn du das falsch verstehst, ist das nicht mein Problem. :p
@pointercrash
Das ist übrigens vollkommen legal in ISO C und nennt sich Bitfelder.
-
Danke @groovemaster,
damit habe ich wohl die Absolution, zukünftig einheitlich alle C- Compiler damit zu traktieren
.
War mir nie so ganz schlüssig drüber ...Zurück zur eigentlichen Frage, wenn das mit den Bitfields einheitlich geregelt ist, ist die Frage damit beantwortet
... oder immer noch nicht?
-
Ich persönlich würde es ehrlich gesagt trotzdem nicht mit Bitfeldern machen. Auch wenn das keine Empfehlung für andere sein soll.
Erstens ist dies nicht effizienter, weil ein Compiler dann auch nur das macht, was hier bereits als Beispiel "manuell" gemacht wurde. Klar, eine Plattform könnte theoretisch mit einer CPU ausgestattet sein, die nativen Zugriff auf Bits erlaubt. Das liegt dann aber sowieso ausserhalb des Standards, da die kleinste adressierbare Einheit ein Byte (also char) darstellt. Und zweitens, in deinem Beispiel werden Unions eher missbraucht, da sie eigentlich dafür gedacht sind, dass sich zwei oder mehr unabhängige Objekte den selben Speicher teilen, und nicht ein Objekt auf unterschiedliche Art und Weise angesprochen werden kann. IdR funktioniert das zwar, weil die Member einer Union an der selben Adresse beginnen. Es ist vom konzeptionellen Aspekt aber nicht ganz astrein.