Logik

Logische Verknüpfungen bilden die Grundbausteine von logischen Schaltkreisen, welche in modernen Prozessoren verwendet werden. Hierbei werden binäre Eingangssignale aufgrund fester Regeln in binäre Ausgangssignale umgewandelt. In der Programmierung werden binäre Werte für die Speicherung von Wahrheitswerten verwendet und boolsche Werte genannt.

Boolsche Werte werden in C mit den Zahlen 0 und 1 representiert. C benutzt folgende Operatoren, um binäre Werte miteinander zu verknüpfen:

Die Operatoren der Negation NOT erwarten einen Operanden und drehen den jeweiligen Wahrheitswert um, aus 0 wird 1 und vice versa. Die anderen Operatoren erwarten zwei Operanden und verknüpfen sie gemäss folgender Wahrheitstabelle:

    | EQU |  OR | AND | XOR
----+-----+-----+-----+-----
0 0 |  1  |  0  |  0  |  0
0 1 |  0  |  1  |  0  |  1
1 0 |  0  |  1  |  0  |  1
1 1 |  1  |  1  |  1  |  0

Details

In den Sprachen C und C++ wird bei binären Operationen unterschieden zwischen logischen und bitweisen Operatoren. Die logischen Operatoren fassen die gegebenen Operanden je als einen boolschen Wert auf. Die bitweisen Operatoren hingegen fassen jedes Bit der Operanden als boolschen Wert auf und führen für jedes Bit die Verknüpfung aus. Im Falle von Operationen mit zwei Operanden werden somit bei den bitweisen Operatoren sämtliche Bits paarweise miteinaner verknüpft. Beispiele sind bei den jeweiligen Operatoren aufgeführt.

Es ist zu beachten, dass der logische XOR-Operator grundsätzlich nicht existiert. Da jedoch die Verknüpfung zweier boolschen Werte mit dem Ungleich-Operator != denselben Effekt hat, wird selbiger auf dieser Seite der Vollständigkeit halber als XOR-Operator aufgeführt.

Wenn ein nicht-boolscher Wert in einen boolschen Wert umgewandelt wird, so wird jeglicher Wert, welcher zu 0 auswertet als false und jeglicher Wert, der nicht zu 0 auswertet, als true angenommen.

Die logischen Operatoren werden hauptsächlich für Bedingungen verwendet, die bitweisen Operatoren hauptsächlich für Masken.

Bedingungen

Kontrollstrukturen benötigen normalerweise einen boolschen Wert, um je nachdem einen bestimmten Programmteil auszuführen, oder nicht. Der Ausdruck, welcher zu dem entscheidenden boolschen Wert führt, wird Bedingung genannt und steht jeweils in runden Klammern () nach dem entsprechenden Kontrollstruktur-Keyword.

Eine Bedingung wird wie eine normale Anweisung geschrieben und auch als solche betrachtet. Das abschliessende Semikolon ; wird jedoch innerhalb der runden Klammern weggelassen. Nur bei der for-Schleife steht die Bedingung getrennt durch Semikolons ; an zweiter Stelle innerhalb der runden Klammern ().

Eine Bedingung wird stets als boolscher Wert ausgewertet. Dementsprechend sind die logischen Operatoren NOT !, AND && und OR || sehr häufig in Bedingungen anzutreffen. Genauso jedoch liefern Vergleichs-Operatoren wie Kleiner < und Grösser > einen boolschen Wert und werden grundsätzlich bei numerischen Vergleichen für Bedingungen verwendet.

Wenn als Bedingung ein Pointer-Typ angegeben wird, so wird dieser gemäss obengenannten Regeln als boolscher Wert ausgewertet. Dies bedeutet, dass sämtliche Pointer zu true auswerten, es sei denn, es handelt sich um einen Null-Pointer. Vorsicht: Weder die Sprachen C oder C++ selbst, noch irgend ein Compiler initialisieren Pointer automatisch auf Null. Dies muss stets manuell vorgenommen werden.

Umsteiger von anderen Sprachen auf C oder C++ seien an dieser Stelle zudem gewarnt, dass der Gleichheits-Operator == in C zwei Gleichheitszeichen == hat und nicht eines. Beim Operator mit einem Gleichheitszeichen = handelt es sich um den Zuweisungsoperator.

Masken

Die bitweisen Operatoren NOT ~, AND &, OR | und XOR ^ sowie die entsprechenden Zuweisungsoperatoren werden hauptsächlich für low-level Programmierung verwendet, wie beispielsweise in der Systemprogrammierung. Da sie einzelne Bits verändern, wird der Umgang mit diesen Operatoren auch häufig als Bit-fiddling (Bit-Schwindeleien, auch zu verstehen als Bit-Gebastel, oder auf gut Schweizerdeutsch: Umegfätterle mit Bittli) bezeichnet.

Diese Operatoren werden jedoch auch im normalen Programmieralltag verwendet, insbesondere, um sogenannte Masken zu bearbeiten. Masken sind Einstellungen, gespeichert als Folge von Bits, wobei jedes Bit eine Einstellung darstellt. Die einzelnen Bits werden auch als Flags (Flaggen, Markierungen) bezeichnet. Folgendes ist ein Beispiel von gängigen Maskenoperationen:


0001
0010
0100
1000  



Initializing with flags, m = 0011
Setting a flag,          m = 0111
Switching a flag,        m = 1111
Testing a flag               1111
deleting a flag,         m = 1110
enum mask{
  VALID     = 0x01,
  RUNNING   = 0x02,
  COMPUTING = 0x04,
  ERROR     = 0x08,
};

int main(){
  enum mask m = VALID | RUNNING;
  m |= COMPUTING;
  m ^= ERROR;
  if(m & ERROR) {
    m &= ~VALID;
  }
  return 0;
}
Nächstes Kapitel: Zahlensysteme