Einleitung: Warum kann man in Rust nicht einfach eine Zahl mit einem String addieren?
\n\nWenn Sie von Python oder JavaScript kommen, sind Sie es gewohnt, etwas wie str(42) oder 42 + "" zu schreiben. In Rust funktioniert dieser Trick nicht. Der Compiler fragt streng: "Welchen Typ möchtest du haben? Integer? String? Entscheide dich!"
Die Frage "How do I convert from an integer to a string?" ist eine der beliebtesten auf Stack Overflow im Bereich Rust. Tausende Entwickler zerbrechen sich den Kopf, warum ihr Code nicht kompiliert, wenn sie versuchen, Folgendes zu schreiben:
\n\nlet number = 42;\nlet text = number; // Fehler: expected `&str`, found `i32`\n\nHeute werfen wir einen Blick unter die Haube dieser Konvertierung. Sie erfahren nicht nur wie man es macht, sondern auch wie es funktioniert – auf der Ebene von Traits, Allokationen und sogar Assembler. Los geht's!
\n\nDer einfachste Weg: Die Methode to_string()
\n\nIn Rust haben, wie in den meisten modernen Sprachen, die ganzzahligen Typen eine Methode to_string(). Sie sieht täuschend einfach aus:
fn main() {\n let num: i32 = 255;\n let s: String = num.to_string();\n println!("{}", s); // Gibt aus: "255"\n}\n\nDies funktioniert für alle ganzzahligen Typen: i8, u32, i64, usize usw.
Was passiert unter der Haube?
\n\nDie Methode to_string() ist keine Compiler-Magie. Sie ist über den Trait Display implementiert. In der Standardbibliothek von Rust gibt es diese Implementierung:
// Vereinfachte Version aus der Standardbibliothek\nimpl<T: fmt::Display> ToString for T {\n #[inline]\n fn to_string(&self) -> String {\n use fmt::Write;\n let mut buf = String::new();\n // Hier wird die Methode fmt() des Traits Display aufgerufen\n let _ = buf.write_fmt(format_args!("{}", self));\n buf.shrink_to_fit(); // Speicheroptimierung\n buf\n }\n}\n\nDer entscheidende Punkt: to_string() erzeugt einen neuen String auf dem Heap. Jeder Aufruf ist eine Speicherallokation. Bei Hunderttausenden von Konvertierungen kann dies zu einem Leistungsengpass werden.
Alternative: Das Makro format!
\n\nDie zweite beliebte Methode ist das Makro format!. Es funktioniert wie println!, gibt aber anstatt in die Konsole einen String zurück:
fn main() {\n let num = 1024;\n let s = format!("{}", num);\n println!("Länge des Strings: {}", s.len()); // 4\n}\n\nDer Unterschied zwischen to_string() und format! ist minimal. to_string() ruft intern format_args! und write_fmt auf. Im Grunde ist es dasselbe. Die Wahl ist eine Frage des Stils und der Lesbarkeit.
Wann sollte man format! verwenden?
\n- \n
- Wenn eine Zahl in die Mitte eines Strings eingefügt werden soll:
format!("Zahl: {}", num)\n - Wenn das Format komplex ist (hexadezimal, mit Trennzeichen):
format!("{:#x}", 255)→ "0xff" \n - Wenn die Ausdruckskraft des Codes wichtig ist \n
Trait Display vs ToString: Was ist schneller?
\n\nWenn Sie eine Bibliothek oder leistungskritischen Code schreiben, verwenden Sie direkt den Trait Display über write! in einen Puffer. Dies ermöglicht die Wiederverwendung von bereits allokiertem Speicher:
use std::fmt::Write;\n\nfn main() {\n let num = 42;\n let mut buffer = String::with_capacity(20); // Speicher vorab allokieren\n\n // Zahl in den Puffer schreiben\n write!(buffer, "{}", num).unwrap();\n println!("{}", buffer); // "42"\n\n // Leeren und wiederverwenden\n buffer.clear();\n write!(buffer, "{}", 256).unwrap();\n println!("{}", buffer); // "256"\n}\n\nDieser Ansatz bietet eine 2-3x Leistungssteigerung in Schleifen, in denen wiederholt Zahlen in Strings konvertiert werden müssen, da die Speicherallokation nur einmal erfolgt.