about summary refs log tree commit diff
path: root/lang/zig/pointers.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lang/zig/pointers.zig')
-rw-r--r--lang/zig/pointers.zig93
1 files changed, 93 insertions, 0 deletions
diff --git a/lang/zig/pointers.zig b/lang/zig/pointers.zig
new file mode 100644
index 0000000..92c0d9d
--- /dev/null
+++ b/lang/zig/pointers.zig
@@ -0,0 +1,93 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const bytesAsSlice = std.mem.bytesAsSlice;
+
+test "address of syntax" {
+    // Get the address of a variable:
+    const x: i32 = 1234;
+    const x_ptr = &x;
+
+    // Dereference a pointer:
+    expect(x_ptr.* == 1234);
+
+    // When you get the address of a const variable,
+    // you get a const pointer to a single item.
+    expect(@TypeOf(x_ptr) == *const i32);
+
+    // If you want to mutate the value,
+    // you'd need an address of a mutable variable:
+    var y: i32 = 5678;
+    const y_ptr = &y;
+    expect(@TypeOf(y_ptr) == *i32);
+    y_ptr.* += 1;
+    expect(y_ptr.* == 5679);
+}
+
+test "pointer array access" {
+    // Taking an address of an individual element gives a
+    // pointer to a single item. This kind of pointer
+    // does not support pointer arithmetic.
+    var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    const ptr = &array[2];
+    expect(@TypeOf(ptr) == *u8);
+
+    expect(array[2] == 3);
+    ptr.* += 1;
+    expect(array[2] == 4);
+}
+
+test "pointer slicing" {
+    var array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    const slice = array[2..4];
+    expect(slice.len == 2);
+
+    expect(array[3] == 4);
+    slice[1] += 1;
+    expect(array[3] == 5);
+}
+
+test "comptime pointers" {
+    comptime {
+        var x: i32 = 1;
+        const ptr = &x;
+        ptr.* += 1;
+        x += 1;
+        expect(ptr.* == 3);
+    }
+}
+
+test "@ptrToInt and @intToPtr" {
+    const ptr = @intToPtr(*i32, 0xdeadbee0);
+    const addr = @ptrToInt(ptr);
+    expect(@TypeOf(addr) == usize);
+    expect(addr == 0xdeadbee0);
+}
+
+test "comptime @intToPtr" {
+    comptime {
+        const ptr = @intToPtr(*i32, 0xdeadbee0);
+        const addr = @ptrToInt(ptr);
+        expect(@TypeOf(addr) == usize);
+        expect(addr == 0xdeadbee0);
+    }
+}
+
+test "volatile" {
+    const mmio_ptr = @intToPtr(*volatile u8, 0x12345678);
+    expect(@TypeOf(mmio_ptr) == *volatile u8);
+}
+
+test "pointer casting" {
+    const bytes align(@alignOf(u32)) = [_]u8{ 0x12 } ** 4;
+    const u32_ptr = @ptrCast(*const u32, &bytes);
+    expect(u32_ptr.* == 0x12121212);
+
+    // Even this example is contrived,
+    // there are better ways to do the above than pointer casting.
+    // For example, using a slice narrowing cast:
+    const u32_value = bytesAsSlice(u32, bytes[0..])[0];
+    expect(u32_value == 0x12121212);
+
+    // And even another way, the most straightforward way to do it:
+    expect(@bitCast(u32, bytes) == 0x12121212);
+}