דלג לתוכן הראשי

מצביע

מודל Wave של זיכרון מסוג בצוא מפורש

ב-Wave, עיצוב מצביע מבוסס על מודל Wave של זיכרון מסוג בצוא מפורש. מודל זה שואף להגדיר מצביעים ומערכים כסוג זיכרון מפורש ברמת השפה, ולא באופן הסוואה או הפשטה ספרייתית.

בהתאם לעיצוב זה, ב-Wave מצביע מיוצג כסוג בפורמט ptr<T>, שמראה במפורש שזהו סוג שמצביע על כתובת זיכרון שאוגרת ערכים מסוג T. שיטה זו מתייחסת לציין כחלק ממערכת הסוגים ולא כהצהרת אוצרת או פועלת, כך שניתן לבטא מבנה זיכרון בצורה יותר ברורה ועקבית.


ב-Wave, מצביע הוא סוג מפורט בפורמט ptr<T>. לקבלת כתובת השתמש ב-&, לדפרנס השתמש ב-deref.

הכרזה ואתחול

var x: i32 = 10;
var p: ptr<i32> = &x;

סוג המצביע ניתן לשכפל.

var p1: ptr<i32> = &x;
var p2: ptr<ptr<i32>> = &p1;

דפרנס

var x: i32 = 10;
var p: ptr<i32> = &x;

println("{}", deref p); // 10
deref p = 20;
println("{}", x); // 20

חוקי סמל מילולי null

null הוא סמל מילולי רישמי. לא מזוהה ואין להשתמש בו כשם משתנה.

חוקי יסוד:

  • ניתן להקצות את null רק ליעד ptr<T>.
  • לא ניתן להקצות סוגים שאין להם מצביע כמו i32, bool, array<...>.
  • לא ניתן לאתחל את המצביע עם ליטרל מספר שלם (0, 123, -1 וכו'). משתמש במפורש ב-null.
var p: ptr<i32> = null;
var arrp: ptr<array<i32, 3>> = null;

// var n: i32 = null; // שגיאה
// var b: bool = null; // שגיאה

אריתמטיקת מצביעים

Wave תומכת באריתמטיקת מצביעים הבאה.

  • ptr + int: Pointer Forwarding מבוסס GEP
  • int + ptr: פעולה זהה
  • ptr - int: Pointer Backwarding מבוסס GEP
  • ptr - ptr: חישוב ההבדל בבתים i64

נקודות:

  • ptr<T> +/- n נע לפי גודל T (sizeof(T)).
  • כלומר, ptr<i32> + 3 זז לפי בייטים פלוס +12.
var base: ptr<i32> = 0x1000 as ptr<i32>;

var p1: ptr<i32> = base + 3; // 0x1000 + 12
var p2: ptr<i32> = 2 + base; // 0x1000 + 8
var p3: ptr<i32> = base - 1; // 0x1000 - 4

var diff: i64 = p1 - base; // 12 (הפרש בתים)

השוואת מצביעים

ניתן להשתמש במצביעים עבור השוואה.

if (p == null) { ... }
if (p != null) { ... }
if (p1 == p2) { ... }

היחס עם מערכים

מערך מצביעים:

var a: i32 = 10;
var b: i32 = 20;
var arr: array<ptr<i32>, 2> = [&a, &b];
println("{} {}", deref arr[0], deref arr[1]);

מצביע מערך:

var p: ptr<array<i32, 3>> = &[1, 2, 3];
if (p != null) {
println("{}", deref p[1]);
}

פתק בטיחות

כיום Wave אינה בעלת מודל בטיחות מצביעים מבוסס בעלות/חיים כמו Rust. לכן, אינו חוסם באופן אוטומטי null הפניה הפוכה. מומלץ להכניס דפוס בדיקה null מפורש לפני deref.