C Bitoperationen mit Char (8 Bit)

raven16

Lieutenant
Registriert
Nov. 2008
Beiträge
580
Ich habe als Aufgabe, den Status von 8 Lampen in einem Char (Byte) zu speichern.
Den logischen Aufbau des Programms und die richtigen Bitoperatoren habe ich schon fertig.
Nur hab ich noch ein Problem dabei und ich finde da nicht wirklich gute Beispiele zu:

Ich habe ein Char angelegt:
Code:
unsigned char lampenspeicher = '0';
Ein Char ist ja 1 Byte = 8 Bit groß und reicht für die Speicherung. Unsigned deswegen, damit ich die Werte von 0-255 nutzen kann.

Wenn ich die Lampe ein oder aus Schalten möchte, dann benutze ich folgende Bitoperationen
Code:
//Lampe einschalten
if(schalter == true) lampenspeicher = lampenspeicher |= operand;
//Lampe ausschalten
else if(schalter == false)
{
	lampenspeicher = lampenspeicher |= operand;
	lampenspeicher = lampenspeicher ^= operand;
}
Ich weiß nicht so genau, wie ich die Variable operand anlegen soll, damit die Bitoperation funktioniert.
Bis jetzt ist die Variable operand bei mir ein Integer mit den Werten für die jeweilige Lampe (1,2,4,8,16,32,64,128), je nachdem welche Lampe ein oder ausgeschaltet werden soll.
Aber char mit Bitoperation int geht ja nicht oder?

Danke :)
 
Ich weiß nicht so genau, wie ich die Variable operand anlegen soll, damit die Bitoperation funktioniert.
operand= Pow(2, Lampe), da 2 ^ 0 = 1, 2 ^ 1 = 2 usw - mit Lampe im Bereich [0-7].
 
Zuletzt bearbeitet:
Ich versteh deine Frage auch nicht wirklich.
Wenn du einzelne bits in einem char setzen/löschen willst, verwende folgendes:

Code:
unsigned char lampenspeicher;

// Bit 5 setzen:
lampenspeicher |= (1 << 5);

// Bit 6 löschen:
lampenspeicher &= ~(1<<6);

edit://
Du hast da wohl "|" und "|=" durcheinander gebracht. Ein "|" ist ein binäres oder, ein "|=" ist ein binäres oder mit Zuweisung. Folgende Statements sind also äquivalent:
Code:
x = x | 123;
x |= 123;
 
Das ist der Grund warum ich diese Operationen benutze, und ich würde das gerne auch beibehalten, weil ich mir das immerhin selbst so überlegt habe :D
Code:
/* #### Bit-Operationen
 * Es gibt gibt 4 Fälle, die durch die (fehlerhafte) Eingabe auftreten können:
 * 1. Lampe an, wenn Lampe noch nicht an:
 * z.B.	10011001
 * OR	00100000´
 * =	10111001
 * 2. Lampe an, wenn Lampe schon an ist:
 * z.B. 10111001
 * OR	00100000
 * =	10111001
 * 3. Lampe aus, wenn Lampe an ist:
 * z.B. 10111001
 * OR 	00100000
 * =	10111001
 * XOR	00100000
 * =	10011001
 * 4. Lampe aus, wenn Lampe schon aus ist:
 * z.B. 10011001
 * OR	00100000
 * =	10111001
 * XOR	00100000
 * = 	10011001
 *
 * 1. und 2. müssen gleiche Operatoren haben, damit die einzelne Lampe immer angeschaltet wird
 * 3. und 4. müssen gleiche Operatoren haben, damit die einzelne Lampe immer ausgeschaltet wird
 */

Gut der Wert '0' müsste, wenn man in der Ascii-tabelle nachschaut, nen anderen Wert haben. Wie initialisiere ich dann den lampenspeicher, damit alle Bits auf null gesetzt sind?
Code:
unsigned char lampenspeicher = 0x00

Ja gut dann benutze ich die operationen ohne gleich
 
Zuletzt bearbeitet:
Wenn du ihm schon die Hausaufgaben machst, wäre ein Wort zur Erklärung vielleicht ganz hilfreich.
Ich bin jetzt nicht so der große Erklärbär, aber ich versuche es zumindest mal. Das Setzen des Bits
sollte trivial sein, aber das Löschen vielleicht weniger.

Code:
a &= ~(1 << b);
Der Bitshiftoperator (<<) setzt die 1 an die gewünschte Stelle. Der NOT-Operator (~) setzt alle 0-Bits
auf 1 und alle 1-Bits auf 0. Der AND-Operator (&, duh) sorgt dafür, dass nur noch die im rechten Teil
des Ausdrucks gesetzten Bits übrig bleiben.

Anschaulich: Wir haben a = 01001011 und wollen das vierte Bit löschen (von der kleinsten signifikan-
ten Stelle an). Der Ausdruck lautet dann:

Code:
a &= ~(1 << 3);

Wir verschieben das Bit nur um drei Stellen, denn am Anfang ist es ja schon beim ersten Bit. Im ersten
Schritt kommt heraus:

Code:
01001011 &= ~(00001000);
Der NOT-Operator schaltet die Bits um:
Code:
01001011 &= 11110111;

Der AND-Operator lässt nur noch die gesetzten Bits übrig:

Code:
    01001011
AND 11110111
    --------
    01000011

Hoffe, das war irgendwie nachvollziehbar.
Ergänzung ()

raven16 schrieb:
Code:
unsigned char lampenspeicher = 0x00
Manchmal ärgere ich mich echt, dass ich Leuten nur vor den Kopf gucken kann. Dann allerdings: Welch Grauen würde mich erwarten?
Wie wäre es mit sowas hier:

Code:
Peter = 0;
 
Gut der Wert '0' müsste, wenn man in der Ascii-tabelle nachschaut, nen anderen Wert haben. Wie initialisiere ich dann den lampenspeicher, damit alle Bits auf null gesetzt sind?

Da du grundsätzlich mit Zahlen arbeitest, ist der char-Datentyp nicht passend. Nimm doch einfach den int-Datentyp, also:
Code:
int lampenspeicher = 0;
 
3murmeln schrieb:
Da du grundsätzlich mit Zahlen arbeitest, ist der char-Datentyp nicht passend. Nimm doch einfach den int-Datentyp, also:
Code:
int lampenspeicher = 0;

Das erinnert mich an Martin Sonneborn. Ich danke Ihnen für diese Frage und möchte stattdessen eine andere beantworten.

raven16 schrieb:
Ich habe als Aufgabe, den Status von 8 Lampen in einem Char (Byte) zu speichern.
 
Juhu es klappt die Initialisierung mit 0x00 :D
habe operand jetzt vom int auch zum char gemacht und jetzt folgendermaßen initialisiert (0x00 | mit 00 = Hexawert)
Code:
//Operand für die betroffene Lampe festlegen, der für die Bitoperation benötigt wird
switch(lampe)
{
	case '1':
		operand = 0x01;
		break;
	case '2':
		operand = 0x02;
		break;
	case '3':
		operand = 0x04;
		break;
	case '4':
		operand = 0x08;
		break;
	case '5':
		operand = 0x10;
		break;
	case '6':
		operand = 0x20;
		break;
	case '7':
		operand = 0x40;
		break;
	case '8':
		operand = 0x80;
		break;
	default:
		error = true;
}
Ergänzung ()

3murmeln schrieb:
Da du grundsätzlich mit Zahlen arbeitest, ist der char-Datentyp nicht passend. Nimm doch einfach den int-Datentyp, also:
Code:
int lampenspeicher = 0;

Ne geht nicht, weil die Aufgabenstellung vom Prof. besagt, dass ich ein char nehmen muss für die Speicherung :D
 
Ach Schande - da gibt sich asdfman so viel Mühe, um dir Bitshifting und Vernotten näher zu bringen - und Du ignoriest ihn einfach. ;)

@ asdfman

Was ist eigentlich an operand = pow(2, lampe) so übel? Allemal kürzer als der o.s. switch. :p
 
Zuletzt bearbeitet:
asdfman schrieb:
Wenn du ihm schon die Hausaufgaben machst, wäre ein Wort zur Erklärung vielleicht ganz hilfreich.
Ich bin jetzt nicht so der große Erklärbär, aber ich versuche es zumindest mal. Das Setzen des Bits
sollte trivial sein, aber das Löschen vielleicht weniger.

Danke für die ausführliche Erklärung.
Ich werde das bestimmt noch öfters demnächst brauchen, daher finde ich das sehr gut und verständlich erkärt und findet definitiv noch Verwendung bei mir.

Dem Peter=0 entnehme ich, dass es egal ist ob man ein char mit dezimalwerten initialisiert oder mit hexawerten oder liege ich da immernoch falsch?
 
3murmeln schrieb:
Was ist eigentlich an operand = pow(2, lampe) so übel? Allemal kürzer als der o.s. switch. :p
Schlimmer geht natürlich immer. pow() aufzurufen ist aus vielen Gründen schlecht. Ein praktischer Grund ist, dass man dazu
die math lib einlinken muss und das OP kaum zuzumuten ist. Dann natürlich, dass nicht offensichtlich ist, was man damit
bezwecken will. Ein Bitshift gibt nicht nur das selbe gewünschte Ergebnis sondern ist auch noch intuitiv. Dann natürlich
Performance und vielleicht noch dass es als Lösung für OPs Hausaufgabe kaum akzeptiert werden würde, weil damit
das eigentliche Thema verfehlt wird.

Und: Der Ausdruck, den du da beim ersten Mal gepostet (und gerade heimlich korrigiert) hast ist auch noch sinnlos und falsch.

Dem Peter=0 entnehme ich, dass es egal ist ob man ein char mit dezimalwerten initialisiert oder mit hexawerten oder liege ich da immernoch falsch?
Eine Zahl ist eine Zahl ist eine Zahl. Egal welche Basis sie hat.
 
3murmeln schrieb:
Da du grundsätzlich mit Zahlen arbeitest, ist der char-Datentyp nicht passend. Nimm doch einfach den int-Datentyp, also:
Code:
int lampenspeicher = 0;

Wenn schon, dann lieber unsigned int. Bit-Operationen auf vorzeichenbehafteten Typen sind mit diversen Einschränkungen behaftet, die ich jedes mal wieder nachlesen muß, um sie 5 Minuten später wieder zu vergessen ... aber sicher ist sicher. Deshalb wenn immer möglich, vorzeichenlose Typen für Bit-Operationen verwenden.
 
Zuletzt bearbeitet: (miserable Rechtschreibung :-\)
Wenn wir gerade dabei sind, dann könnte man evtl. noch ein paar Worte zu XOR verlieren. Unter Umständen hat man nur einen Schalter zum An- und Ausschalten einer Lampe. Benutzt man nun den Ansatz mit OR zum Setzen und AND zum Rücksetzen muss man jedesmal zunächst den Status abfragen um zu wissen was man denn jetzt machen muss. Mit XOR kann man gezielt Bits togglen und muss sich in dem geschilderten Fall keine Sorgen um den aktuellen Status machen.

11110000
10011001 XOR
-------------
01101001

Es dreht also genau die Stellen an denen der Operand 1 ist um.
 
3murmeln schrieb:
Meine Güte - komm mal runter - es ist schließlich Sonntag...

Hier, für dich.
IMG_1742.JPG


Jetzt vertragen wir uns wieder, ok? :3
 

Ähnliche Themen

Zurück
Oben