Letzte Änderung: 13.10.2024
Die Programmiersprache Rust hat eine strenge Typisierung, die Datentypen von Variablen müssen bereits zur Kompilierzeit eindeutig festgelegt sein (statische Typisierung).
Die elementaren Datentypen (auch einfache oder primitive Datentypen genannt) haben einen endlichen Wertebereich aus skalaren Werten, d.h. sie setzen sich nicht aus mehreren Werten zusammen. Rust kennt folgende elementare Datentypen:
Bezeichnung | Länge | Wertebereich |
---|---|---|
i8 | 8 Bit | -128 bis 127 |
u8 | 8 Bit | 0 bis 255 |
i16 | 16 Bit | -32.768 bis 32.767 |
u16 | 16 Bit | 0 bis 65.535 |
i32 | 32 Bit | -2.147.483.648 bis 2.147.483.647 |
u32 | 32 Bit | 0 bis 4.294.967.295 |
i64 | 64 Bit | ca. -9*1018 bis 9*1018 |
u64 | 64 Bit | 0 bis ca. 18*1018 |
i128 | 128 Bit | ca. -1038 bis 1038 |
u128 | 128 Bit | 0 bis ca. 3*1038 |
isize | Maschinenabhängig | |
usize | Maschinenabhängig |
Die Bitlänge der Typen isize
und usize
hängt von der Architektur des Computers ab, auf dem das Programm läuft. Sie beträgt beispielsweise 32 Bit auf einer 32-Bit-Architektur und 64 Bit auf einer 64-Bit-Architektur.
Zu allen oben aufgelisteten Datentypen lässt sich der jeweils kleinste und größte Wert des Wertebereichs sowie die Bitlänge über typspezifische Konstanten ermitteln. Beim Datentyp i64
wären das beispielsweise
i64::MIN = -9223372036854775808
i64::MAX = -9223372036854775807
i64::BITS = 64
Numerische Literale können in Rust in unterschiedlichen Notationen dargestellt werden:
Darstellung | Beispiel |
---|---|
Dezimal | 1_234 |
Hexadezimal | 0xff |
Oktal | 0o77 |
Binär | 0b1111_0000 |
Byte (nur u8 ) | b'A' |
Zur besseren Lesbarkeit dürfen numerische Literale das visuelle Trennzeichen _
enthalten.
Rust interpretiert numerische Literale standardmäßig als i32
, wenn keine weitere Typinformation vorhanden ist. Allerdings kann man einen abweichenden Datentyp wie folgt angeben:
let a: u8 = 12; let b = 12u8;
Rust führt bei numerischen Literalen eine automatische Typkonvertierung durch, d.h. das Literal 12
lässt sich problemlos einer Variablen vom Typ u8
zuweisen. Bei der Zuweisung einer Variablen an eine andere Variable ist Rust hingegen strikt und führt keine automatische Typkonvertierung durch, sondern verlangt stets eine explizite Typkonvertierung (casting):
let a: u8 = 12; let b: u16 = a; // Typfehler! let b: u16 = a as u16; // Korrekt mit expliziter Typkonvertierung
Gleitkommazahlen (auch Fließkommazahlen) sind Zahlen mit Komma in der Dezimalschreibweise. Rust kennt folgende zwei Typen:
Bezeichnung | Länge | Wertebereich | Bedeutung |
---|---|---|---|
f32 | 32 Bit | ca. -3*1038 bis 3*1038, -∞, ∞, NaN | Einfache Genauigkeit |
f64 | 64 Bit | ca. -10308 bis 10308, -∞, ∞, NaN | Doppelte Genauigkeit |
Wenn bei einem Gleitkommazahl-Literal der Typ nicht explizit angegeben ist, interpretiert es der Rust-Compiler standardmäßig als f64
.
let a: f32 = 1.2; // f32 let b = 1.2f32; // f32 let c = 1.2; // f64
Bezeichnung | Länge | Wertebereich | Bedeutung |
---|---|---|---|
bool | 8 Bit | true , false | Boolescher Typ |
char | 32 Bit | Alle Unicode-Skalarwerte | Zeichen-Typ |
() | 0 Bit | () | Einheitstyp (unit type) |
! | 0 Bit | Niemals-Typ (never type) |
Der Datentyp char umfasst nicht nur alle gängigen alphanumerischen Zeichen auf der Tastatur, sondern auch Unicode-Sonderzeichen:
let a: char = 'A'; let b: char = '👍'; let c: char = '✅'; let d: char = '🦀';
Zusammengesetzte Datentypen (auch Verbund-Typen genannt) bestehen aus mehreren skalaren Einzelwerten.
Syntax | Bedeutung |
---|---|
[T; N] | Array mit Einträgen vom Typ T und der festen Länge N. |
(T), | Tupel |
struct T {...} | Struktur |
enum T {...} | Aufzählung (enum) |
Beispiele:
let a: [i32; 5] = [1, 2, 3, 4, 5]; let b = a[0]; // erstes Element let tup: (i16, f32, u8) = (500, 6.4, 1); let (x, y, z) = tup; // Tupel destrukturieren struct User { username: String, email: String, } let a = User { username: String::from("benutzername123"), email: String::from("jemand@example.com"), }; let b = a.username; // auf einzelnes Feld zugreifen enum IpAddrKind { V4(u8, u8, u8, u8), V6(String), } let home = IpAddrKind::V4(127, 0, 0, 1); let loopback = IpAddrKind::V6(String::from("::1"));
Syntax | Bedeutung |
---|---|
fn Name(Parameter) | Funktion |
&variable[..] | Anteilstyp (slice) |
&str | Zeichenkettenanteilstyp (string slice) |
&T | Referenz |
*const T | Roher Zeiger (unsafe) |
Bei Funktionsdefinitionen muss zu jedem Parameter stets der Datentyp mit angegeben werden. Hat die Funktion einen Rückgabewert, muss auch dessen Typ angegeben werden.
Beispiele:
fn addieren(a: i64, b: i64) -> i64 { a + b } let a = addieren(5, 7); // ergibt 12
let v = vec![1, 2, 3, 4, 5]; let first = &v[0];
let a: &str = "Hallo"; let b: &str = &a[0..1]; // Teilzeichenfolge "H"
let a = String::from("Hallo"); let b = &a; // hat den Typ &String let mut c = String::from("Hallo"); let d = &mut c; // hat den Typ &mut String
let a: u8 = 12; let b: *const u8 = &a; // roher Zeiger auf die konstante Variable a let mut c: u8 = 13; let d: *mut u8 = &mut c; // roher Zeiger auf die veränderbare Variable c