Zuweisungen
Zuweisung von numerischen Daten
Die Zuweisung einer Konstante, Variable oder eines Ausdrucks an eine Variable erfolgt mit dem Zuweisungsoperator =.
Im weiteren Verlauf dieses Kapitels wird davon ausgegangen, dass eine short-Variable 2 Bytes und eine long-Variable 4 Bytes belegen. Wie erwähnt, kann dies je nach System/Compiler abweichen. Jedoch ändert sich dadurch nichts am grundlegenden Verhalten der nachfolgend beschriebenen Konvertierungen bei unterschiedlichen Datentypen.x
Bei der Zuweisung sind drei Fälle zu unterscheiden:
1. Wertebereiche beider Operanden sind gleich.
In diesem Fall ist bei der Zuweisung keine Anpassung erforderlich und die Zuweisung erfolgt ohne Informationsverlust.
2. Linker Operand besitzt größeren Wertebereich als rechter Operand und beide Datentypen besitzen den gleich Vorzeichentyp.
In diesem Fall wird der rechte Operand durch den Compiler automatisch vorzeichenrichtig auf den Datentyp des linken Operanden erweitert und es geht keine Information verloren. Dies wird besonders deutlich bei der Zuweisung in Zeile 7 im Beispiel, in der eine short-Variable einer long-Variable zugewiesen wird.
#include <print>
int main()
{
// Zuweisung short an long-Variable
short sVal = -10; // = 0xFFF6
long lVal = sVal; // = 0xFFFFFFF6
std::println("sval: {}, lVal: {}",sVal,lVal);
//Zuweisung unsigned char an unsigned long-Variable
unsigned char bVal = 128; // = 0x80
unsigned long dwVal = bVal; // = 0x00000080
std::println("bVal: {}, dwVal: {}",bVal, dwVal);
}
sval: -10, lVal: -10
bVal: 128, dwVal: 128
3. Linker Operand besitzt kleineren Wertebereich als rechter Operand oder die Operanden besitzen unterschiedliche Vorzeichentypen.
In diesem Fall wird der rechte Operand Byte für Byte in den linken Operanden kopiert, beginnend mit dem niederwertigsten Byte. Die Anzahl der kopierten Bytes richtet sich dabei nach der Größe des linken Operanden. D.h., wird einer char-Variable ein long-Datum zugewiesen, wird nur das niederwertige Byte des long-Datums übernommen. Dabei kann es, wie im Beispiel in Zeile 14 zu sehen ist, zu recht seltsamen Ergebnissen kommen.
#include <print>
int main()
{
// Zuweisung long-Variable an eine short-Variable
long lVal = -186L; // = 0xFFFFFF46
short wVal = lVal; // = 0xFF46 = -186
std::println("short=long -> {}={}",wVal,lVal);
// Zuweisung unsigned long an unsigned char-Variable
unsigned long dwVal = 128UL; // = 0x00000080
unsigned char bVal = dwVal; // = 0x80
std::println("uchar=ulong -> {}={}",bVal,dwVal);
// Achtung! Zuweisung unsigned long an char-Variable
signed char cVal = dwVal; // 0x80 = -128
std::println("schar=ulong -> {}={}",cVal,dwVal);
}
short=long -> -186=-186
uchar=ulong -> 128=128
schar=ulong -> -128=128
Bei der Konvertierung eines Gleitkommadatums in ein Integer-Datum werden die Nachkommastellen abgeschnitten, d.h. es erfolgt keine Rundung.
Soll sichergestellt werden, dass bei der Zuweisung keine Information verloren geht, ist der Ausdruck rechts vom Zuweisungsoperator in geschweifte Klammern einzuschließen. In diesem Fall überprüft der Compiler beim Übersetzen des Programms, ob der rechte Operand ohne Informationsverlust zugewiesen werden kann und gibt ansonsten eine Fehlermeldung aus. Diese Überprüfung zur Compilezeit wird als preventing narrowing bezeichnet.
// Definition/Initialisierung long Variable
long var1 = -128L;
// Zuweisung long an short -> Fehlermeldung
short var2 = { var1 };
Zuweisung von Zeichen- und String-Literalen
Wird ein Zeichen-Literal einer Variable zugewiesen, sollte die Variable vom Datentyp char sein. Das zuzuweisende Zeichen wird in Hochkommas eingeschlossen, wie im Kapitel Konstanten dargestellt. Das Gleiche gilt ebenfalls für wide-character Zeichen. Die Variable sollte dann vom Datentyp wchar_t sein und das zuzuweisende Zeichen ist mit dem Präfix L zu versehen. Wird ein Zeichen einem anderen Datentyp als char zugewiesen, erfolgt, wie bei numerischen Daten, eine Typkonvertierung vom Datentyp char aus.
Bei der Zuweisung eines String-Literals (String ohne Präfix) an eine Variable, muss die Variable den Datentyp Zeiger auf const char besitzen. Um einen const char-Zeiger zu definieren, folgt nach dem Datentyp const char und vor dem Variablennamen ein * (Sternchen), so wie im nachfolgenden Beispiel dargestellt. Dem Zeiger kann später im Programmverlauf ein weiteres String-Literal zugewiesen werden, da hier nicht der Zeiger konstant ist, sondern das, worauf er verweist, also das String-Literal. Mehr zu Zeigern später.
#include <print>
#include <iostream>
int main()
{
// Zuweisungen von Zeichen
char charA = 'A'; // = 0x41
char linef = '\n'; // = 0x0A
std::print("char:{}{}",charA,linef);
// Zuweisungen von wide character
wchar_t chA = L'A'; // = 0x0041
wchar_t lf = L'\n'; // = 0x000A
std::wcout << "wchar:" << chA << lf;
// Zuweisungen von Strings
const char *pText; // const char-Zeiger
pText = "Dies ist ein String!";
std::println("Text:{}",pText);
}
char:A
wchar:A
Text:Dies ist ein String!
Mehrfach-Zuweisung
Bei der Mehrfach-Zuweisung wird ein Datum mehreren Variablen in einer Anweisung 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.
#include <print>
int main()
{
// Variablendefinitionen
short sVar1, sVar2;
signed char cVar;
// Zuweisungen short = short = int(0xFF)
sVar1 = sVar2 = 0xFF;
std::println("sVar1:{}, sVar2:{}",sVar1,sVar2);
// Zuweisung short = signed char = int(0xFF)
sVar1 = cVar = 0xFF; // Ergebnis: cVar=-1, sVar1=-1
std::println("sVar1:{}, cVar:{}",sVar1,cVar);
// Zuweiung signed char = short = int(0xFF)
cVar = sVar1 = 0xFF; // Ergebnis: sVar1=255, cVar=-1
// char Datum als Zahl ausgeben!
std::println("cVar:{:d}, sVar1:{}",cVar,sVar1);
}
sVar1:255, sVar2:255
sVar1:-1, cVar:-1
cVar:-1, sVar1:255
Vermeiden Sie bei Mehrfach-Zuweisungen die Verwendung von Variablen mit unterschiedlichen Datentypen. Dies kann sonst, wie in der letzten Zuweisung oben dargestellt, zu unliebsamen Überraschungen führen.
Übungen
assign_01
Geben Sie den ganzzahligen Teil der Konstante pi aus der Standardbibliothek aus.
Definieren Sie eine char-Variable letterA und initialisieren sie mit dem Buchstaben A. Geben Sie die Variable letterA als Buchstabe, als Dezimalwert und als Hexadezimalwert aus. Tipp: Sehen Sie sich dazu den Formatierungsstring für die Ausgabe im Kapitel Standardausgabe an.
Der Integerteil von Pi ist: 3
Inhalt der Variable 'letterA' ist: A
Und 'letterA' als Wert: 65
In Hex-Darstellung: 0x41
assign_02
Definieren Sie eine short-Variable shortValue und initialisieren diese mit dem Hex-Wert 7fff. Geben Sie die Variable als Dezimalzahl aus.
Weisen Sie die Variable shortValue einer signed char-Variable charValue zu.
Weisen Sie die Variable charValue einer long-Variable longValue zu.
Geben Sie die Variablen charValue und longValue als Dezimalzahlen aus. Welche Werte werden ausgegeben und warum?
short-Wert 0x7fff ist in dezimal: 32767
charValue: ???
longValue: ???