From ee9b8fc921f48dc893808e1c9dbfbef321aa362c Mon Sep 17 00:00:00 2001 From: Nguyễn Gia Phong Date: Sun, 28 Feb 2021 17:18:03 +0700 Subject: [lang/zig] Learn some Zig --- lang/zig/pointers.zig | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 lang/zig/pointers.zig (limited to 'lang/zig/pointers.zig') 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); +} -- cgit 1.4.1