C++ Tutorial

 Operatoren

Allgemein gilt: Operatoren können nur Operanden mit gleichen Datentypen verarbeiten. Sind die Datentypen nicht identisch, werden sie auf einen gemeinsamen Datentyp konvertiert. Mehr zur Typkonvertierung später.

Zuweisungen

Zuweisung von numerischen Daten

Die Zuweisung eines Datums oder eines Ausdrucks an eine Variable erfolgt mit dem Zuweisungsoperator =. Besitzt der linke Operand den gleichen oder einen größeren Wertebereich und haben beide Operanden den gleichen Vorzeichentyp, wird der rechte Operand vorzeichenrichtig erweitert.

Besitzt der linke Operand einen kleineren Wertebereich oder einen anderen Vorzeichen-Datentyp als der rechte Operand, werden nur die niederwertigsten Bytes des rechten Operanden übernommen. D.h., es geht in diesem Fall Information verloren.

Bei einer Zuweisung eines Gleitkomma-Datentyps an einen Integer-Datentyp wird nur der ganzzahlige Teil übernommen. Es erfolgt keine Rundung.

// Header-Dateien einbinden
#include <iostream>
#include <format>

int main()
{
   // Variablen definieren
   unsigned short toAssign = 0xba94;
   float fvar = 1.23f;
   unsigned char ucvar;
   short svar;
   unsigned short usvar;
   unsigned long ulvar;
   // Zuweisungen testen
   // unsigned short = unsigned
   short usvar = toAssign;
   std::cout << std::format("ushort = ushort: {:#x}\n", usvar);
   // unsigned long = unsigned short
   ulvar = toAssign;
   std::cout << std::format("ulong = ushort: {:#x}\n", ulvar);
   // unsigned char = unsigned short
   ucvar = toAssign;
   std::cout << std::format("uchar = ushort: {:#x}\n", ucvar);
   // short = unsigned short
   svar = toAssign;
   std::cout << std::format("short = ushort: {:#x}\n", svar);
   // short = float
   svar = fvar;
   std::cout << std::format("short = float: {}\n", svar);
}

Zuweisung von Zeichen- und String-Literalen

Wird ein Zeichen-Literal einer Variable zugewiesen, sollte die Variable vom Datentyp char sein.

Bei der Zuweisung eines String-Literals an eine Variable muss die Variable den Datentyp Zeiger auf const char besitzen. Um einen const char-Zeiger zu definieren, wird nach dem Datentyp const char und vor dem Variablennamen ein * (Sternchen) gestellt.

// Header-Dateien einbinden
#include <iostream>
#include <format>

int main()
{
   // char- und Variablen definieren
   char cvar1, cvar2;
   // Daten zuweisen
   cvar1 = 'A';    // Buchstabe A
   cvar2 = '\n';   // Linefeed
   // char-Daten ausgeben
   std::cout << std::format("{}{}", cvar1, cvar2);
   // const char-Zeiger definieren
   const char *pstr;
   // String zuweisen
   pstr = "Ich bin ein String!\n";
   // String ausgeben
   std::cout << pstr;
}

Mehrfach-Zuweisung

Bei der Mehrfach-Zuweisung wird mehreren Variablen in einer Anweisung der gleiche Wert zugewiesen. Die einzelnen Variablen werden mit dem Zuweisungsoperator verkettet und rechts wird der zuzuweisende Ausdruck angegeben. Die Zuweisungen erfolgen in der Reihenfolge von rechts nach links.

int main()
{
   // Variablendefinitionen
   short sVar1, sVar2;
   char cVar;

   // Zuweisungen
   sVar1 = sVar2 = 0xFF;  // Ergebnis: sVar2=255, sVar1=255
   sVar1 = cVar = 0xFF;   // Ergebnis: cVar=-1, sVar1=-1
   cVar = sVar1 = 0xFF;   // Ergebnis: sVar1=255, cVar=-1!
}

Rechenoperationen

Für Berechnungen stehen die Rechenoperationen Addition +, Subtraktion -, Multiplikation * und Division / zur Verfügung. Diese Operationen sind sowohl auf Integer- wie auch auf Gleitkomma-Daten anwendbar. Ferner steht für Integer-Daten noch der Modulo-Operator % zur Verfügung, der den Rest einer Division berechnet. Bei allen Operationen gilt: Punkt- vor Strichrechnung.

Beachten Sie, dass eine Division von zwei Integer-Daten als Ergebnis ebenfalls ein Integer-Datum liefert. Soll das Ergebnis ein Gleitkomma-Datum sein, muss vor der Division eine Typkonvertierung durchgeführt werden (wird in einem weiteren Kapitel erläutert).

#include <iostream>
#include <format>

int main()
{
   // int-Variablen definieren/initalisieren
   int ivar1 = 10, ivar2 = 3;
   // int-Division berechnen
   auto res1 = ivar1 / ivar2;
   // Rest einer int-Division berechnen
   auto res2 = ivar1 % ivar2;
   // Ergebnisse ausgeben
   std::cout << std::format("10 / 3 = {}\n10 % 3 = {}\n", res1, res2);
}

Kurzschreibweisen

Für häufig benötigte Rechenoperationen stellt C++ eine Reihe von Kurzschreibweisen bereit, die in der nachfolgenden Tabelle aufgeführt sind.

Operator
Rechenoperation
x++
Erhöht x um 1 nach dessen Auswertung
++x
Erhöht x um 1 vor dessen Auswertung
x--
Vermindert x um 1 nach dessen Auswertung
--x
Vermindert x um 1 vor dessen Auswertung
x += y
x = x + y
x -= y
x = x - y
x *= y
x = x * y
x /= y
x = x / y
x %= y
x = x % y
#include <iostream>
#include <format>

int main()
{
   // Zwei int-Variablen definieren/initialisieren
   int var1 = 11, var2 = 3;
   // var1 inkrementieren
   var1++;
   // var1 durch var2 dividieren
   var1 /= var2;
   // var1 ausgeben
   std::cout << std::format("var1: {}\n", var1);
   // var2++ var1 zuweisen, Ausgabe beachten!
   var1 = var2++;
   std::cout << std::format("var1: {}, var2: {}\n", var1, var2);
   // ++var2 var1 zuweisen, Ausgabe beachten!
   var1 = ++var2;
   std::cout << std::format("var1: {}, var2: {}\n", var1, var2);
}

Bit- und Schiebeoperationen

Bit- und Schiebeoperationen sind nur für Integer-Daten zugelassen. Bis auf den Bitoperator 'rechts schieben' arbeiten alle Bit- und Schiebeoperatoren vorzeichenunabhängig.

Operator
Syntax
Ergebnis
&
OP1 & OP2
AND: Liefert als Ergebnis nur an den Stellen ein 1-Bit, an denen beide Operanden ein 1-Bit besitzen.
|
OP1 | OP2
OR: Liefert als Ergebnis an den Stellen ein 1-Bit, an denen einer der Operanden ein 1-Bit besitzen.
^
OP1 ^ OP2
XOR: Liefert als Ergebnis an den Stellen ein 1-Bit, an denen beide Operanden unterschiedliche Bits besitzen
~
~OP1
NOT: Liefert an den Stellen ein 1-Bit, an denen der Operand ein 0-Bit besitzt und umgekehrt.
<<
OP1 << OP2
SHIFT LEFT: Schiebt die Bits des Operanden OP1 um OP2 Positionen nach links.
>>
OP1 >> OP2
SHIFT RIGHT: Schiebt die Bits des Operanden OP1 um OP2 Positionen nach rechts.

Genauso wie bei den Grundrechenoperationen stehen auch für die Bit- und Schiebeoperationen entsprechende Kurzschreibweisen zur Verfügung:

Operator
Operation
x &= y
x = x & y
x |= y
x = x | y
x ^= y
x = x ^ y
x <<= y
x = x << y
x >>= y
x = x >> y
#include <iostream>
#include <format>

int main()
{
   // Zwei Variablen definieren
   unsigned short var1 = 0xaa55, var2 = 0x00ff;
   // Inhalt der Variablen als Hex-Zahlen ausgeben
   std::cout << std::format("Als Hex-Zahlen var1: {:#06x}, var2: {:#06x}\n", var1, var2);
   // Verunden der beiden Variablen
   std::cout << std::format("var1 & var2: {:#06x}\n", var1 & var2);
   // XOR der beiden Variablen
   std::cout << std::format("var1 ^ var2: {:#06x}\n", var1 ^ var2);
   // var1 um 4 Bits nach links
   var1 <<= 4;
   std::cout << std::format("var1 <<= 4: {:#06x}\n", var1);
   // var2 um 4 Bits nach rechts
   var2 >>= 4;
   std::cout << std::format("var2 >>= 4: {:#06x}\n", var2);
}

Vergleichs- und Logikoperationen

Die Vergleichs- und Logikoperatoren werden hauptsächlich in Verzweigungen und Programmschleifen eingesetzt, die später behandelt werden. Beide Operatorgruppen liefern als Ergebnis der Operation den bool-Wert true oder false zurück.

Operator
Syntax
Operation
<
EXP1 < EXP2
true, wenn Ergebnis von Ausdruck EXP1 kleiner als Ergebnis von Ausdruck EXP2
<=
EXP1 <= EXP2
true, wenn Ergebnis von Ausdruck EXP1 kleiner oder gleich Ergebnis von Ausdruck EXP2
==
EXP1 == EXP2
true, wenn Ergebnis von Ausdruck EXP1 gleich Ergebnis von Ausdruck EXP2
!=
EXP1 1= EXP2
true, wenn Ergebnis von Ausdruck EXP1 ungleich Ergebnis von Ausdruck EXP2
>= 
EXP1 >= EXP2
true, wenn Ergebnis von Ausdruck EXP1 größer oder gleich Ergebnis von Ausdruck EXP2
>
EXP1 > EXP2
true, wenn Ergebnis von Ausdruck EXP1 größer als Ergebnis von Ausdruck EXP2
&&
EXP1 && EXP2
true, wenn Ergebnis von Ausdruck EXP1 und EXP2 gleich true
||
EXP1 || EXP2
true, wenn Ergebnis von Ausdruck EXP1 oderEXP2 gleich true
!
! EXP
true, wenn Ergebnis von Ausdruck EXP false ist
#include <iostream>
#include <format>

int main()
{
   // Variablen definieren
   short var1 = 10, var2 = 5;
   std::cout << std::format("var1, var2: {},{}\n", var1, var2);
   // Vergleichsoperationen
   // Klammern wegen der besseren Lesbarkeit
   auto res = (var1 < var2);
   std::cout << std::format("var1 < var2: {}\n", res);
   // Logikoperationen
   res = ((var1 == 10) && (var2 == 2));
   std::cout << std::format("(var1 == 10) && (var2 == 2): {}\n", res);
   res = ((var1 > 5) || (var2 >= 10));
   std::cout << std::format("(var1 > 5) || (var2 >= 10): {}\n", res);
}

Rangfolge der Operatoren

Nachfolgend in tabellarischer Form die Rangfolge aller Operatoren. In der Tabelle gilt: Operatoren in der Gruppe 1 werden vor den Operatoren der Gruppe 2 ausgeführt usw. Durch entsprechendes Setzen von Klammern kann die Reihenfolge der Operationen abgeändert werden.

Gruppe
Operator
Operation
1
::
Zugriffsoperator
2
(...)
Funktionsaufruf
[...]
Indizierung

->
Indirekter Zugriff auf Member

.
Direkter Zugriff auf Member

++ und --
Post-Inkrement/Dekrement

DTYP(...)
Typkonvertierung
3
! und ~
NOT und Negation
+ und -
Vorzeichen
++ und ++
Pre-Inkerement/Dekrement
&
Adressoperator
*
Dereferenzierungsoperator
sizeof
Belegter Speicherplatz (Bytes)
new und delete
Dynamische Speicherverwaltung
DTYP (...)
Typkonvertierung
co_wait
Coroutine unterbrechen
4
.* und ->*
Indirekter Zugriff auf Member
5
* und / und %
Arithmetische Operatoren
6
+ und -
Arithmetische Operatoren
7
<< und >>
Scheibeoperatoren
8
<=>
3-Wege-Vergleichsoperator
9
<= und <
Vergleichsoperatoren
>= und >
Vergleichsoperatoren
10
== und !=
Vergleichsoperatoren
11
&
UND Bitoperator
12
^
XOR-Bitoperator
13
|
ODER Bitoperator
14
&&
logischer UND-Operator
15
||
logischer ODER-Operator
16
?..:
Bedingungsoperator
= und *=
/= und +=
%= und +=
-= und &=
^= und <<=
>>=
Zuweisungsoperatoren
throw
Ausnahme auslösen
co_yield
Coroutine unterbrechen
17
,
Komma-Operator