Question regarding address and pointer

Hi,
I have a question regarding the address of a constant array. I am writing a WASM module that simply returns a string.

// The actual string I want to return
const name: []const u8 = "huntrss";
// An array that contains the address to the string and it length
// The WASM runtime I use will later read from this array to get the address and length
// of the string
var return_value: [2]i32 = [_]i32{0} ** 2;

pub export fn name() callconv(.C) i32 {
    const name_address = @intCast(i32, @ptrToInt(&name));
    return_value[0] = name_address;

    const name_length = @intCast(i32, name.len);
    return_value[1] = name_length;

    // The following lines I do not fully understand, but I trial-an-errored them:
    // Get the address to the first element of the return_value address
    const ptr_to_return_value: *i32 = &return_value[0];
    // Dereference the pointer to get the "actual" address of return_value
    const ptr = @intCast(i32, ptr_to_return_value.*);
    return ptr;
}

So what I don’t understand, as mentioned above is, why I need to dereference the pointer again to get the address. I could debug the resulting WASM module and I indentified that the wrong address was returned. That’s why I came up with the idea to dereference it again.

Can someone explain to me, why I need to dereference the pointer, please?

Thanks in advance

Edit:

I am using zig version 0.10.1.

2 Likes

I’m curious if you have tried other built-ins, such as @intFromPtr?

The documentation isn’t as clear as I’d like it to be, but it may be worth checking out:

@intFromPtr:

Converts value to a usize which is the address of the pointer. value can be *T or ?*T.

To convert the other way, use @ptrFromInt

I’m running this code here:

var return_value: [2]i32 = [_]i32{0} ** 2;

const print = @import("std").debug.print;

pub fn main() !void 
{
    const p1: *i32 = &return_value[0];

    const p2: *[2]i32 = &return_value;

    print("\n\n{any}\n\n{any}\n\n", .{@intCast(i32, @intFromPtr(p1)), @intCast(i32, @intFromPtr(p2))});
}

And here is what it produces:

2416648

2416648

Just a note - here in, @intCast is changing so that the first argument will not be necessary: Major zig language update just landed: removal of destination type from all cast builtins - #4 by AndrewCodeDev

1 Like

Thanks for the reply. I did not know about @intFromPtr. However I forgot to mention that I am using 0.10.1 where it is not available. I will check the implementation of @intFromPtr in the zig master version to find how it is implemented.

I think I see the problem. The original type of that string literal is *[7:0]const u8. By defining name to be a slice, you case the pointer to coerce to a slice value. A slice is its own chunk of memory that holds both pointer and length (same as what you’re doing explicitly with return_value).

In this line you’re taking the pointer of the slice, which is not what you want. To obtain the underlying pointer that the slice refers to you have to do name.ptr.

I think from there you will be able to fix the rest of the program to obtain what you want.

2 Likes

That does the trick. Thanks @kristoff.

1 Like