Kapitel 06 - Boolesche Logik und Bitoperationen

Peter Ulbrich

🚀 by Decker

RĂŒckblick

  • Bisher kennengelernt:
    • BinĂ€rformat
      • Wertigkeit der Bits im BinĂ€rsystem
      • Verteilung der Bits auf mehrere Bytes fĂŒr Zahlen >=255
      • Verschiedene Stellenwertsysteme (Dezimal, Hexadezimal, BinĂ€r, Oktal)
    • Boolesche Operatoren
      • AND, OR, NOT
  • Jetzt:
    • Boolesche Logik (Interpretation/Bedeutung von BinĂ€rwerten)
    • Bitweise Operatoren/Operationen

RĂŒckblick - BinĂ€rformat

  • Computer speichert Informationen im BinĂ€rformat:

    1 oder 0 (= genannt Bit)

  • Kombination von mehreren Ziffern bildet BinĂ€rzahl: 1001

  • Jede Stelle der BinĂ€rzahl steht fĂŒr eine Zweierpotenz:

    \(2^0 = 1, 2^1 = 2, 2^2 = 4, 2^3 = 8, ...\)

  • Beispiel
    • Darstellung der Zahl 79 = 64 + 8 + 4 + 2 + 1
128 64 32 16 8 4 2 1
0 1 0 0 1 1 1 1

RĂŒckblick - BinĂ€rformat

  • Zahlen \(> 255\) werden genauso dargestellt, bestehen aber aus mehreren Bytes
  • Beispiel: 591 = 512 + 79
512 256 128 64 32 16 8 4 2 1
1 0 0 1 0 0 1 1 1 1
  • 591 = 0000 0010 x 256 + 0100 1111

RĂŒckblick - BinĂ€rformat

  • Byte mit dem höchsten/niedrigsten Wert heißt Most/Least Significant Byte (MSB bzw. LSB)
  • Reihenfolge der Bytes heißt Byte Order: Entweder von MSB zu LSB (Big Endian) oder von LSB zu MSB (Little Endian)
  • Analog fĂŒr Bits: Most/Least Significant Bit (MSBit bzw. LSBit)
128 64 32 16 8 4 2 1
0 (MSBit) 1 0 0 1 1 1 1 (LSBit)

RĂŒckblick - BinĂ€rformat

  • 🚹 Achtung: Zahlen können gleich aussehen, aber in unterschiedlichen Zahlensystemen stehen
  • Beispiel: 110 (BinĂ€r) ≠ 110 (Dezimal)
  • Unterscheidung bei gemischten Zahlensystemen ĂŒber Index: 110B = 6D
  • Gibt mehrere gĂ€ngige Zahlensysteme:
    • Dezimal → D oder dec
    • BinĂ€r → B oder bin
    • Hexadezimal → H oder hex
    • Oktal → O oder oct

RĂŒckblick - Wahrheitswerte

  • Ein Ausdruck, der zu true oder false evaluieren kann, heißt boolescher Ausdruck

Logischer Datentyp (bool)

  • Zum Speichern von Wahrheitswerten „wahr“ und „falsch“ (Boolean)
  • Wertevorrat: true und false
  • Datendefinition: bool b;
  • Zuweisung: b = true;

Logische Operatoren

Name Symbol Beispiel
UND
(AND)
&& b && (x < 7)
ODER
(OR)
|| b || x > 8
Negation
(NOT)
! !b

Den Umgang mit boolescher Logik lernen wir jetzt kennen!

Operatoren der booleschen Algebra

Notationen der Logikoperatoren

Operation Bool. Algebra C
UND \(A\wedge B\) A && B
ODER \(A\vee B\) A || B
NEGATION \(\overline{A}\) !A

\(\bf{A\wedge B}\)

fig/menge-intersection.svg

\(\bf{A\vee B}\)

fig/menge-union.svg

\(\bf{\overline{A}}\)

fig/menge-excluding.svg

Wahrheitstabelle Oder

  • OR: true, sobald mindestens einer der beiden TeilausdrĂŒcke wahr ist
A B \(A \vee B\)
0 0 0
1 0 1
0 1 1
1 1 1

\(\bf{A\vee B}\)

fig/menge-union.svg

Wahrheitstabellen Und

  • AND: true, sobald beide TeilausdrĂŒcke wahr sind
A B \(A \wedge B\)
0 0 0
1 0 0
0 1 0
1 1 1

\(\bf{A\wedge B}\)

fig/menge-intersection.svg

Wahrheitstabellen Negation

  • NOT: Gegenteil des ursprĂŒnglichen Werts
A \(\overline{A}\)
0 1
1 0

\(\bf{\overline{A}}\)

fig/menge-excluding.svg

Boolesche Algebra

  • Boolesche AusdrĂŒcke können natĂŒrlich mehr als zwei Variablen beinhalten

    → Schrittweise Evaluierung von links nach rechts

  • Setzt Klammern, um eindeutige Auswertungsreihenfolge zu erzwingen → Lesbarkeit

  • Beispiel: (!A && B) || (A && !B)

    bool A = false; bool B = true;

fig/boolean-eval-tree.svg

Regeln der booleschen Algebra

  • Erlauben Umformen von booleschen AusdrĂŒcken
  • Ermöglichen Vereinfachung von langen und komplexen booleschen AusdrĂŒcken
  • Gesetze sind (meist) einfach zu verstehen
  • Ergeben sich intuitiv aus der Mengenlehre
  • Anmerkung: Anschauliche, vertiefende Literatur mit vielen Übungsaufgaben ist
    • Thomas L. Floyd - Digital Fundamentals [1]
    • Gedacht fĂŒr Elektrotechniker, auf Englisch
fig/floyd-digital-fundamentals.jpg

Regeln der booleschen Algebra

Kommutativgesetz

  • \(A \vee B = B \vee A\)
  • \(A \wedge B = B \wedge A\)

Assoziativgesetz

  • \((A \vee B) \vee C = A \vee (B \vee C)\)
  • \((A \wedge B) \wedge C = A \wedge (B \wedge C)\)

Distributivgesetz

  • \(A \wedge (B \vee C) = (A \wedge B) \vee (A \wedge C)\)
  • \(A \vee (B \wedge C) = (A \vee B) \wedge (A \vee C)\)
  • OR kann wie eine Addition gesehen werden

    → Alt. Schreibweise: \(A \vee B = A + B\)

  • AND wie eine Multiplikation

    → Alt. Schreibweise: \(A \wedge B = AB\)

  • Es gilt: „Punkt vor Strich“

  • Erleichtert das „Rechnen“ mit booleschen AusdrĂŒcken

Regeln der booleschen Algebra

  • DarĂŒber hinaus gelten auch noch weitere Regeln:
Bool. Algebra C
1. \(A \wedge 1 = A\) (A && true) → A
2. \(A \wedge 0 = 0\) (A && false) → false
3. \(A \vee 0 = A\) (A || false) → A
4. \(A \vee 1 = 1\) (A || true) → true
5. \(A \vee A = A\) (A || A) → A
6. \(A \vee \overline{A} = 1\) (A || !A) → true

Regeln der booleschen Algebra

Bool. Algebra C
7. \(A \wedge A = A\) (A && A) → A
8. \(A \wedge \overline{A} = 0\) (A && !A) → false
9. \(\overline{\overline{A}} = A\) !(!A) → A
10. \(A \vee (A\wedge B) = A\) (A || (A && B)) → A
\(\Rightarrow A (1 \vee B)\) Faktorisierung (Distributivgesetz)
\(= A \wedge 1\) Regel 4: \(1 \vee B = 1\)
\(= A\)
11. \(A \vee \overline{A}B = A \vee B\) (A || (!A && B)) → (A || B)

Die Herleitung von Regel 11 schauen wir uns einmal als Beispiel an

Beispiel - Herleitung einer Regeln zur booleschen Algebra

Herleitung: \(A \vee \overline{A}B = A \vee B\)

\(A + \overline{A}B\)
\(= (A + AB) + \overline{A}B\) Regel 10: \(A = A + AB\)
\(= (AA + AB) + \overline{A}B\) Regel 7: \(A = AA\)
\(= AA + AB + A\overline{A} + \overline{A}B\) HinzufĂŒgen von: \(A\overline{A} = 0\)
\(= (A + \overline{A})(A + B)\) Faktorisierung
\(= 1 (A + B)\) Regel 6: \(A + \overline{A} = 1\)
\(= A + B\)

Regeln der booleschen Algebra

  • Ein zweites Beispiel: \((A \vee B)(A \vee C) = A \vee BC\)
\((A + B)(A + C)\)
\(=AA + AC + AB + BC\) Distributivgesetz
\(=A + AC + AB + BC\) Regel 7: \(A = AA\)
\(=A (1 + C) + AB + BC\) Faktorisierung (Distributivgesetz)
\(=A + AB + BC\) Regel 4: \(1 + C = 1\)
\(=A (1+ B) + BC\) Faktorisierung (Distributivgesetz)
\(=A + BC\) Regel 4: \(1 + B = 1\)

De-Morganschen Regeln

  • Abschließend gibt es noch zwei wichtige Regeln nach De-Morgan:
Bool. Algebra C
1. \(\overline{AB} = \overline{A} \vee \overline{B}\) !(A && B) → !A || !B
2. \(\overline{(A \vee B}) = \overline{A} \wedge \overline{B}\) !(A || B) → !A && !B

Die De-Morganschen Regeln gelten auch fĂŒr mehr als zwei Variablen:

\(\overline{ABC} = \overline{A} \vee \overline{B} \vee \overline{C}\)

Das war jetzt genug Theorie. ZurĂŒck zu C!

Short-Circuiting

  • In C gibt es einen Mechanismus namens Short-Circuiting fĂŒr AND und OR
  • Boolesche TeilausdrĂŒcke werden von links nach rechts evaluiert
  • Steht Gesamtergebnis schon nach ersten Teilausdrucks fest → keine weitere Auswertung

Beispiel - Short-Circuiting

  • Short-Circuiting fĂŒr OR:

    Linker Ausdruck ist true

if (true || ((A && B) || !C)) {
    run_critical_function();
} else {
// ...
  • Short-Circuiting fĂŒr AND:

    Linker Ausdruck ist false

if (false && (A || B)) {
    run_critical_function();
} else {
// ...

Vorteile von Short-Circuiting

  • Short-Circuiting bietet Geschwindigkeitsvorteile:

    Lohnenswert, unkomplizierte AusdrĂŒcke als erstes zu evaluieren

  • Beispiel:

bool a = true;
if (a || long_complicated_function()) {
    do_stuff();
} else {
    // ...
}

Und nun betrachten wir noch die bitweisen Operationen

Bitweise Operationen

  • Gleichen Operationen wie zuvor fĂŒr die Manipulation von Bits

  • Wichtig: Separate Evaluierung fĂŒr jedes Bit

  • Verkettung von Operationen auch hier möglich

    (Klammern fĂŒr Leserlichkeit und Operator-PrĂ€zedenzen beachten!)

Operation Operator
OR |
AND &
NOT ~
XOR ^
Links-Shift <<
Rechts-Shift >>

(Bitweise Operatoren)

Bitweises Oder

  • Wende OR-Operation separat auf jedes Bit zweier Zahlen an
  • Mindestens ein Bit 1 → Ergebnis ist auch 1
  • Nur 0, falls beide Bits Wert 0 haben
  • Beispiele:
A B A | B
0 0 0
1 0 1
0 1 1
1 1 1
0011 1100 1111
1010 1001 1011

Bitweises Und

  • Wende AND-Operation separat jedes Bit zweier Zahlen an

  • Sind beide Bits 1

    → Ergebnis ist auch 1

  • Beispiele:
A B A & B
0 0 0
1 0 0
0 1 0
1 1 1
0011 1100 0000
1010 1001 1000

Bitweise Negation

  • Invertiere den Wert jedes Bits einer Zahl
  • Beispiele:
A ~A
0 1
1 0
0011 1100
1010 0101

Bitweises exklusives Oder

  • Ist genau ein Bit 1 → Ergebnis ist 1

  • Anders ausgedrĂŒckt:

    Bei Vereinigung zweier Mengen darf ein Element nur in einer Menge existieren

  • HĂ€ufige Notation: \(A\oplus B\)

  • XOR ist reversibel: \((A\oplus B) \oplus B = A\)

fig/menge-xor.svg
  • Beispiele:
A B A ^ B
0 0 0
1 0 1
0 1 1
1 1 0
0011 1100 1111
1010 1001 0011
0011 1001 1010

Anwendung des exklusiven Oders

  • Exklusives Oder ist sehr nĂŒtzliche und viel benutzte Operation
  • Beispiel Kryptographie
    1. Passwort P in Bitmuster ĂŒbersetzen und abschnittsweise auf Text T anwenden

      → Nicht lesbares Ergebnis \(T \oplus P\)

    2. EntschlĂŒsselung: \((T\oplus P) \oplus P = T\)

  • Hamming-Distanz: Bestimmung der Anzahl verschiedener Bits
  • Hashing: Erzeugen einer eindeutigen Signatur (Zwischenschritt, z.B. SHA-3)

Beispiel - Exklusives Oder

  • VerschlĂŒsselung mit fester Passphrase
#include <stdio.h>

int main() {
    int msg = 0x07; // 0000 0111
    int passwd = 0xAA; // 1010 1010
    int enc = msg ^ passwd; // 1010 1101
    printf("%#X\n", enc);
    // Umkehren zu Klartext
    enc ^= passwd; // 0000 0111
    printf("%#X\n", enc);
    return 0;
}
C

Bitschieben - Shifting

  • Verschieben des gesamten Bitmusters um n Bits nach links bzw. rechts
  • Bei fester Bitbreite
    • Links-Shift: n MSBits entfernt
    • Rechts-Shift: n LSBits entfernt
  • Mathematisches Äquivalent
    • Links-Shift: Multiplikation um \(2^n\)
    • Rechts-Shift: Division durch \(2^n\) mit Abrundung
  • Beispiele:
A n A << n
0010 0 0010
0010 1 0100
0010 2 1000
A n A >> n
0101 0 0101
0101 1 0010
0101 2 0001

Beispiel - Bit Shifting

  • Was ist das Ergebnis (GCC-Compiler)?
#include <stdio.h>
int main() {
    int i = 0x1;                // 0001
    printf("%d, %x\n", i, i);
    printf("%d, %x\n", i << 31, i << 31);
    return 0;
}
cpp
  • Undefiniertes Verhalten
  • 0
  • -2 147 483 648 (INT_MIN)
  • -1

Bitmanipulationen

  • HĂ€ufiger Anwendungsfall: Gezielte Manipulation eines oder mehrerer Bits
  • Beispiele:
    • Hardwareprogrammierung
      • Einzelne Bits eines Speicherregisters stehen fĂŒr verschiedene Funktionen (Flags)
      • Aktivierung ĂŒber Setzen des Bits(An-Aus-Schalter)
    • Kommunikation
      • Nachricht mit fester Byte-LĂ€nge
      • Informationen sind an fester Stelle hinterlegt
  • Etablierte Muster: Setzen (Set), Löschen (Clear), Flippen (Toggle) und PrĂŒfen (Check)

Bits setzen

  • Setzen eines Bits ist unkompliziert ĂŒber die OR-Operation möglich
  • In Kombination mit Links-Shift: Setzen eines beliebigen Bits
#include <stdio.h>
int main() {
    int bit_pattern = 0x07;                 // 0111
    bit_pattern = bit_pattern | (1 << 3);
    printf("%#01x\n", bit_pattern);
    return 0;
}
cpp

Achtung: Wegen Operator-PrÀzedenz Klammern beachten!

Löschen eines Bits

  • Löschen eines Bits geschieht mithilfe von Links-Shift, AND und NOT
  • Idee
    • Links-Shift einer 1 bestimmt das Bit
    • Negierung des Ergebnisses → nur ein Bit mit 0
    • Anwenden mit AND

Beispiel - Löschen eines Bits

Beispiel: Bit 2 soll gelöscht werden

  1. Links-Shift um 2 mit (1 << 2)

    Bitmuster: ...0 0100

  2. Negierung: ~(1 << 2)

    Bitmuster: ...1 1011

  3. AND: bit_pattern & ~(1 << 2)

Beispiel - Löschen eines Bits

#include <stdio.h>
int main() {
    int bit_pattern = 0x07;                  // 0111
    bit_pattern = bit_pattern & ~(1 << 2);
    printf("%#01x\n", bit_pattern);
    return 0;
}
cpp

Umkehren eines Bits

  • Umkehren (Flip) eines Bits: Links-Shift in Kombination mit XOR
#include <stdio.h>
int main() {
    int bit_pattern = 0x07;                 // 0111
    bit_pattern = bit_pattern ^ (1 << 1);
    printf("%#01x\n", bit_pattern);
    return 0;
}
cpp

ÜberprĂŒfen eines Bits

  • ÜberprĂŒfen eines Bits: Links-Shift in Kombination mit AND
#include <stdio.h>
int main() {
    int bit_pattern = 0x07;                             // 0111
    printf("Is set: %#01x\n", bit_pattern & (1 << 0));
    return 0;
}
cpp

ÜberprĂŒfen eines Bits

  • ÜberprĂŒfung darf auch als Bedingung verwendet werden
#include <stdio.h>
int main() {
    int bit_pattern = 0x07;                             // 0111
    if (bit_pattern & (1 << 0)) {
        printf("Bit 1 is set\n");
    } else {
        printf("Bit 1 is not set\n");
    }
    return 0;
}
cpp

Typische Verwendung von Bitoperationen

  • Szenario
    • Senden von Nachricht mit fester LĂ€nge
    • Informationen sind fester Stelle der Nachricht zu hinterlegen
  • Beispiel
    • 64 Bit lange Nachricht
    • Bits 16-23 kodieren gemessene Temperatur

Typische Verwendung von Bitoperationen

#include <stdint.h>
#include <stdio.h>

int main() {
    uint64_t message = 0x0;
    uint32_t temperature = 33;                  // 100001
    message |= (temperature << 16) & 0xFF0000;
    printf("temperature = %#01x, message = %#01lx\n",
        temperature, message);
    return 0;
}
cpp

Byte-Reihenfolge (Endianness)

  • Beschreibt Reihenfolge, wie Bytes im Speicher abgelegt werden
  • Ausgangssituation: Eine Zahl mit mehreren Bytes → z. B. int, 4 Bytes
  • Big Endian
32 16 8 4 2 1
0 (MSBit) 0 1 1 1 1 (LSBit)
  • Little Endian
1 2 4 8 16 32
1 (LSBit) 1 1 1 0 1 (MSBit)

Byte-Reihenfolge (Endianness)

  • Warum existiert diese Unterscheidung?
    • Big Endian ist intuitiver (Abbildung wie „ klassische “ Zahlen)
    • Little Endian erlaubt eine einfachere Umwandlung in Datentypen anderer GrĂ¶ĂŸe
  • Beispiel Little Endian
Byte 0 Byte 1 

0x07 0x01 

  • Bei Interpretation bei Zahl als 1 Byte und als 2 Bytes:

    → Start bei gleicher Speicher-Adresse (Bit 0 in Byte 0 → „ganz links“)

Relevanz der Byte-Reihenfolge

  • Verschiedene Prozessorhersteller legten fĂŒr Produkte eine Reihenfolge fest

  • Alternative Bezeichung

    • Motorola-Reihenfolge (Big Endian)
    • Intel-Reihenfolge (Little Endian)
  • Intel, AMD (CPUs fĂŒr Desktop/Laptop) → Little Endian

  • ARM (Mobile/Mikrocontroller) → UnterstĂŒtzen beides

  • Keine Sorge: Compiler ĂŒbernimmt automatisch die Konvertierung

    → Wir mĂŒssen (erst mal) nichts tun! 😀

Zusammenfassung

  • Komplexe ZustĂ€nde mit Boolesche Algebra ausdrĂŒcken
  • Boolesche Operationen fĂŒr die praktische Umsetzung beim Programmieren
  • Short-Circuiting vereinfachen Evaluation von booleschen AusdrĂŒcken
  • Bitweise Operationen erlauben Zugriff auf einzlene Bits BinĂ€rzahl
  • Bitoperationen fĂŒr das Bearbeiten von einzelnen Bits als unerlĂ€ssliches Werkzeug
  • Byte-Reihenfolge: Wichtig fĂŒr verschiedene Anwendungszwecke

Referenzen

[1] T. L. Floyd, Digital Fundamentals, Global Edition, 11. Aufl. London, England: Pearson Education, 2014.
Logo Sys
Kapitel 06 - Boolesche Logik und Bitoperationen