Zeiger
Einführung
Dieses Dokument beschreibt, wie Wave Zeiger verwendet. Wave bietet als Sprache, die Systemprogrammierung auf niedriger Ebene unterstützt, Zeigerfunktionalität an, um explizite Speicheradressmanipulationen zu ermöglichen. Ein Zeiger ist eine Variable, die auf eine Speicheradresse eines bestimmten Typs verweist und ermöglicht direkten Zugriff und Änderung von Werten.
Zeigerdeklaration
In Wave werden Zeiger im Format ptr<Typ>
deklariert. Zum Beispiel kann ein ganzzahliger Zeiger wie folgt deklariert werden:
var p: ptr<i32>;
Diese Deklaration erstellt den Zeiger p
, der auf einen Wert des Typs i32
zeigt.
Zeigerinitialisierung
Ein Zeiger kann mit der Adresse einer Variablen unter Verwendung des &
Operators initialisiert werden:
var a: i32 = 10;
var p: ptr<i32> = &a;
Hier bezieht sich &a
auf die Speicheradresse der Variable a
, und p
wird zum Zeiger, der auf diese Adresse zeigt.
Zeiger-Dereferenzierung
Um den Wert zu lesen oder zu ändern, auf den ein Zeiger zeigt, wird das Schlüsselwort deref
verwendet. Dies wird Dereferenzierung genannt:
var a: i32 = 10;
var p: ptr<i32> = &a;
println("{}", deref p); // Gibt 10 aus
deref p = 20;
println("{}", a); // Gibt 20 aus
NULL-Zeiger
In Wave werden Null-Zeiger durch das Schlüsselwort null
dargestellt.
Zeigervariablen können mit null
initialisiert werden, wobei sie in diesem Fall keinen gültigen Speicher verweisen:
var p: ptr<i32> = null;
Der Compiler wird einen Fehler auslösen, wenn versucht wird, einen Null-Zeiger zu dereferenzieren.
Mehrfachzeiger
Wave unterstützt Mehrfachzeiger. Zeiger können in mehreren Ebenen verschachtelt deklariert und verwendet werden:
var x: i32 = 1;
var p1: ptr<i32> = &x;
var p2: ptr<ptr<i32>> = &p1;
var p3: ptr<ptr<ptr<i32>>> = &p2;
println("{}", deref p1); // 1
println("{}", deref deref p2); // 1
println("{}", deref deref deref p3); // 1
Arrays und Zeiger
Zeiger können sowohl auf Array-Elemente als auch auf das Array selbst zeigen.
Zeiger auf Array-Elemente
var a: i32 = 10;
var b: i32 = 20;
var arr: array<ptr<i32>, 2> = [&a, &b];
println("deref arr[0] = {}, deref arr[1] = {}", deref arr[0], deref arr[1]); // 10, 20
Zeiger auf das gesamte Array
var arr: ptr<array<i32, 3>> = &[1, 2, 3];
println("{}", arr); // Gibt Speicheradresse aus
Sicherheit und Eigentum
Wave führt ein System ähnlich dem von Rust ein, um Speicherstabilität bei der Verwendung von Zeigern durch Besitz- und Lebensdauer zu gewährleisten. Daher werden ungültige Zeigerdereferenzierung, doppelte Freigabe und Dangling-Pointer-Probleme gründlich überprüft, um sie zu verhindern.
fun main() {
let x: i32 = 42;
let p: ptr<i32> = &x;
println("x = {}", deref p);
deref p = 99;
println("x = {}", x);
}
Ausgabe:
x = 42
x = 99
Fazit
Pointer sind eine der wichtigsten Funktionen in Wave, die leistungsstarkes Low-Level-Programmieren ermöglichen. Sie sind sehr nützlich für die Systementwicklung, die native Bibliotheken und die Hardwaresteuerung, wo eine direkte Speicherverwaltung erforderlich ist, und dank der sicheren Compilerstruktur von Wave können die Risiken, die bei der Verwendung von Zeigern auftreten können, wirksam vermieden werden.