Feste Werte, Literale

Ein fester Wert ist ein im Source-Code geschriebener, unveränderbarer Wert, also ein Wert, der nicht aus einem Makro, einer Variablen oder sonstigen Eingabestruktur kommt. In vielen Referenzen werden feste Werte mit dem Begriff Literale bezeichnet. Die Sprachen C und C++ erlauben es, folgende Werte direkt in den Programmcode niederzuschreiben:

Boolean: Ein boolscher Wert ist dasselbe wie ein Wahrheitswert. Es gibt grundsätzlich nur zwei Möglichkeiten. Beispiele: 0, 1

Integer: Ein Integer-Wert ist umgangssprachlich dasselbe wie eine Ganzzahl. Sie kann positiv wie negativ sein, und in C sowohl als Dezimal, Hexadezimal oder Oktalzahl dargestellt werden. Beispiele: 0, 1, 42, 1000000000, 0xffff, 0755

Floating point: Eine Fliesskommazahl (Gleitkommazahl) ist eine Zahl mit Dezimalpunkt (umgangssprachlich: mit Komma). Sie kann auch in Exponentialdarstellung geschrieben werden, die Null vor dem Dezimalpunkt kann weggelassen werden. Beispiele: 3.14159, 12345.67890, .707107, 1e-5, 6.022e23

Character: Ein Character (Buchstabe) ist ein ASCII-Zeichen, welches normalerweise als 1-Byte-Wert codiert wird. Beispiele: 'A', 'x', '\n', '\0', '\x65'

String: Ein String wird als Folge von ASCII-Zeichen aufgefasst mit einem automatisch angehängten '\0'. Beispiele: "Hallo Welt", ""

Pointer: Ein Pointer ist ein Zeiger auf eine Adresse im Speicher. Mit Ausnahme des Null-Pointers sollten diese Werte nicht explizit niedergeschrieben werden, sondern nur anhand der in der Sprache eingebauten Pointer-Arithmetik.

Details

Während Variablen Werte im Speicher oder im Register des Prozessors ablegen, werden feste Werte direkt in den Programmcode integriert und durch den Compiler normalerweise direkt zu den entsprechenden Instruktionen geschrieben und verändern nie ihren Platz. Da sich diese Werte im Programmcode selbst befinden, können sie (üblicherweise) nicht geändert werden.

Der Begriff Literal ist im Englischen sowie allgemein im Compilerbau absolut gebräuchlich, hat jedoch in der Deutschen Programmier-Umgangssprache wenig Fuss gefasst. Viel häufiger werden Literale einfach salopp als Werte bezeichnet. Der Autor hat sich entschieden, auf den Begriff Literal fast gänzlich zu verzichten und stattdessen die Floskel im Quellcode geschriebene feste Werte zu verwenden.

Boolsche Werte

Ein boolscher Wert wird auch Wahrheitswert genannt und kann nur zwei mögliche Zustände annehmen: true und false. Um diese zwei Zustände zu speichern, reicht theoretisch ein Bit aus, in C und C++ werden sie jedoch als Integer-Werte realisiert: In C wird der Wert 0 als false aufgefasst und alle anderen Werte als true. Erst in C++ wurden der Typ bool sowie die Keywords false mittels des 1-Byte-Integer-Wertes 0 und true als Integer-Wert ungleich 0 (normalerweise 1) festgelegt.

Integer-Werte

Integer-Werte sind Ganzzahlen. Wird ein Integer-Wert als fester Wert in den Code geschrieben, so ist er grundsätzlich positiv. Allerding kann mittels des Negativ-Operators - jeder Integer-Wert negiert werden. Mittels des Positiv-Operators + kann ein Integer-Wert auch explizit als positiv markiert werden.

 1234
-1234
+1234

Die Zahl selbst kann als Dezimalzahl (mit den Ziffern 0 bis 9), als Hexadezimalzahl (Ziffern 0 bis 9 und Buchstaben a bis f oder A bis F) mit vorangestelltem 0x oder 0X oder als Oktalzahl (Ziffern 0 bis 7) mit führender 0 geschrieben werden.

9999
0xffff
0755

Die Zahl der benötigten Bytes ermittelt der Compiler anhand des erwarteten Typs an der Stelle des Wertes.

0xff;
0x00ff;
0x000000ff;
unsigned char  a = 0xff;
unsigned short b = 0xff;
unsigned int   c = 0xff;

Auf dem System des Autors ist es zudem möglich, Hexadezimalzahlen mit einem nachgestellten h (nur kleingeschrieben) anzugeben, wobei jedoch die erste Ziffer zwingend eine Zahl von 0 bis 9 sein muss. Um einen Integer-Wert als unsigned zu markieren, kann ihm ein u oder U angehängt werden. Ein entsprechendes Suffix für signed-Werte gibt es nicht. Die Suffixe i oder I und j oder J werden für komplexe Zahlen verwendet, wenn die entsprechende Standardbibliothek eingebunden wird.

0f352h
255u
4i

Einige wenige Compiler erlauben zudem die Angabe von binären Werten mit einem vorangestellten 0b oder 0B oder aber einem nachgestellten kleinen b. Beispiele wären 0b01001011 oder 11001100b. Auf dem System des Autors ist dies jedoch nicht möglich. Ein entsprechendes Pendant für Oktalzahlen ist dem Autor nicht bekannt.

Zur Kennzeichnung einer grossen Zahl ist es zudem möglich, dem Wert ein L (long) oder LL (long long) anzuhängen. Die kleingeschriebenen Pendants l und ll bedeuten dasselbe, allerdings werden auf dieser Seite zur besseren Lesbarkeit die grossgeschriebenen Buchstaben bevorzugt. Diese Typangabe zwingt den Compiler, die dadurch spezifizierte Anzahl Bytes für den Wert zu verwenden. Die Angabe L ist jedoch kaum mehr anzutreffen, da heutzutage ein int-Wert grundsätzlich immer 4 Bytes umfasst (int und long sind in ISO-C++ dasselbe). Der Zusatz L kann jedoch notwendig sein in Programmen, die mittels älteren C-Dialekten compiliert werden. Die Angabe LL hingegen wird auch heute noch verwendet.

1234L
0xffLL

Die Suffixe können grundsätzlich in beliebiger Reihenfolge und durchmischt auftreten. Auf dem System des Autors muss jedoch das Suffix h zuhinterst stehen, kann dafür jedoch (unnützerweise) beliebig oft vorkommen.

4f321LLuihhhhhhh

Fliesskomma-Werte

Fliesskomma-Werte sind Zahlen mit Dezimalpunkt (umgangssprachlich: mit Komma). Im hochdeutschen Sprachraum ist der Begriff Gleitkomma verbreiteter. Sie werden manchmal auch Real-Zahlen genannt, da sie die Menge der reellen Zahlen abzudecken versuchen, allerdings werden sie auf allen gängigen Systemen als Fliesskomma-Zahlen nach IEEE 754 oder IEEE 854 codiert, weswegen auf dieser Seite dieser Begriff verwendet wird. Im Englischen werden sie Floating-Point-Numbers genannt. Sie werden im Dezimalsystem geschrieben, wobei der Punkt . als Dezimalpunkt dient. Wenn vor dem Dezimalpunkt ein Null-Wert steht, so kann dieser Wert weggelassen werden. Genauso kann ein Null-Wert nach dem Dezimalpunkt weggelassen werden. Das Weglassen beider Seiten gleichzeitig ist nicht erlaubt. Der Dezimalpunkt muss in jedem Fall geschrieben werden, da der Wert ansonsten als Integer-Wert aufgefasst wird.

0.1234 == .1234
9876.0 == 9876.

Eine Fliesskomma-Wert kann auch mittels der Exponentialdarstellung geschrieben werden bestehend aus einer positiven oder negativen Mantisse mit optionalem Dezimalpunkt und einem positiven oder negativen ganzzahligen Exponenten, wobei das e oder E als Trennelement dient. Anmerkung: Im Gegensatz zu anderen Sprachen ist in C das Trennelement d oder D nicht erlaubt. Wenn die Mantisse ganzzahlig ist, kann der Dezimalpunkt weggelassen werden.

1.234e56
1e9

In C drei Fliesskomma-Typen spezifiziert: float, double und long double. Ein Fliesskomma-Wert wie oben beschrieben hat den standard-Typ double. Mit dem Suffix f oder F wird ein float-Wert erzwungen, mit dem Suffix l oder L ein long double-Wert. Die Suffixe i oder I und j oder J sind genauso wie bei den Integer-Werten erlaubt und werden auch bei Fliesskomma-Werten für komplexe Zahlen verwendet, wenn die entsprechende Standardbibliothek eingebunden wird.

3.1415f
3.1415
3.1415l
1.i

Es gibt auch die Möglichkeit, Fliesskommazahlen als Hexadezimalwerte zu schreiben. Die Syntax ist 0xM.EpP, wobei M eine positive oder negative ganzzahlige hexadezimale Mantisse, E einen positiven ganzzahligen hexadezimalen Exponenten und P eine Multiplikation der Zahl mit einem positiven oder negativen dezimalen Zweierexponenten darstellt. Der tatsächliche Wert der Fliesskommazahl berechnet sich durch (M + E/16^(hexdigits(E))) * 2^P. Somit representiert beispielsweise 0x12.34p5 durch die Berechnung (0x12 + 0x34/256) * 2^5 die Zahl 582.5. Die Verwendung von hexadezimalen Fliesskommazahlen ist heute nicht mehr gebräuchlich.

Characters

Ein Character ist in C grundsätzlich eine 1-Byte-Ganzzahl, dargestellt als ASCII-Zeichen. Ein solches Zeichen wird immer in einfachen Anführungszeichen '' geschrieben. Einige Dialekte von C verstehen auch multi-Characters, wo innerhalb der einfachen Anführungszeichen 2 bis 8 Zeichen stehen können, dementsprechend bezeichnen die Zeichenfolgen dann eine 2-Byte, 4-Byte oder 8-Byte-Zahl.

char  x = 'A';
short y = 'AA';

Einige Zeichen können oder müssen mittels Escape-Characters geschrieben werden, wobei das Backslash-Zeichen \ als Escape-Zeichen dient. C spezifiziert folgende Escape-Characters, wobei die wichtigsten hervorgehoben sind:

null             0x00
alert            0x07
backspace        0x08
tab              0x09
linefeed         0x0a
vertical tab     0x0b
form feed        0x0c
carriage return  0x0d
escape           0x1b
"                0x22
'                0x27
?                0x3f
\                0x5c
octal
hexadecimal
\0
\a
\b
\t
\n
\v
\f
\r
\e (not all Compilers)
\"
\'
\?
\\
\nnn (example: \101 = 'A')
\xnn (example: \x51 = 'A')

Das Fragezeichen ist deswegen als Escape-Character spezifiziert, da in der Sprache C gewisse Zeichen mittels sogenannter Trigraphen umschrieben werden können. Diese sind zwar auch heute noch in den Compilern eingebaut, werden jedoch nicht mehr bewusst eingesetzt. Weitere Details können auf der Seite über die in C verwendeten Zeichen nachgelesen werden.

Strings

Ein String wird in C als eine Hintereinanderreihung von ASCII-Zeichen aufgefasst. Diese Zeichen werden in doppelten Anführungzeichen "" geschrieben, wobei die oben angesprochenen escape-Zeichen ebenfalls gültig sind. Am Ende eines Strings wird durch den Compiler automatisch ein Null-Byte \0 angehängt, wodurch der tatsächliche Speicherplatzverbrauch des Strings jeweils 1 Byte grösser ist, als die Anzahl Zeichen, die er enthält.





Hello World
#include <stdio.h>

int main(){
  char* str = "Hello World";
  printf(str);
  return 0;
}

Diese Art der Speicherung von Strings mit dem angehängten Null-Byte ist typisch für C und wird oft als null-terminated-String oder manchmal als C-like-String bezeichnet. Die Standardbibliothek string bietet viele Funktionen, um mit diesen Strings zu arbeiten.

Es ist zu beachten, dass fest im Programmcode geschriebene Strings einen Spezialfall der Sprachsyntax darstellen, weswegen ihnen auch ein eigener Name string literals zukommt. String literals speichern ihren Inhalt in einem Array, das zwar normalerweise zugänglich ist, jedoch nicht verändert werden darf. In C++ sind String literals explizit als const markiert und der Compiler warnt vor falscher Anwendung.

Ein String literal befindet sich nach dem Übersetzen durch den Compiler als Datenblock im Binary. Wird das Programm gestartet, so werden diese Daten beim Initialisieren von String-Arrays implizit Byte für Byte durch das Laufzeitsystem kopiert. Dies bedeutet, dass der String in diesem Falle schlussendlich zweimal im Speicher existiert. Nur wenn ein String literal mittels Pointer angesprochen wird, wird es nicht kopiert.

Pointer

Grundsätzlich gibt es nur eine einzige Adresse, die als fester Wert verwendet werden sollte: Der Null-Pointer. Dennoch: Pointer sind Adressen des Speichers und werden nach gängiger Meinung als Ganzzahlen aufgefasst, byteweise durchnummeriert von 0 bis zur letzten Adresse. Es ist somit möglich, einem Pointer eine beliebige Ganzzahl zuzuordnen. Dies brachte in früheren Jahren manchen Computer zum Absturz, heute haben die Betriebssysteme Schutzvorrichtungen, um den Speicher vor unerwünschten Adresszuordnungen zu schützen. Die Sprachen C und C++ bieten dennoch an, Adressen direkt zuzuweisen und insbesonder selbige mittels Pointer-Arithmetik zu manipulieren.

Nächstes Kapitel: Whitespaces