Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to array, returning an array in Zig

I need to create an array in some function (having size as an arg) then return it for easy declare in a single clean line. It already causes a lot of questions as:

  • As I know, Zig has no hidden control and memory allocation, so if I pass an array as an argument will it be cloned, like ints (as it should), or will a pointer be created, as in C or Java?
  • Can functions return an array? If they can, do I need const or comptime as a length value?
  • If I need to pass a pointer to array (or its address) how do I declare it, extract a value from it?
  • If I need to pass a pointer instead of const length: usize how do I do this? If I pass &size compiler says

function expects *usize not const *usize

but I cant rewrite it to const length: *usize because length should be comptime.

Here is example of code I need:

const std = @import("std");

pub fn sorted_array(comptime len: usize) *[]i32 {
    comptime var array: [len]i32 = undefined;
    for (&array, 0..) |*item, i| {
        item.* = @intCast(i);
    }
    return &array;
}

pub fn main() void {
    const size: usize = 10;
    const array: *[]i32 = sorted_array(size);
    for (&array.*) |*item| {
        std.debug.print("{} ", .{item.*});
    }
}

But it does not compile. I also have the same code with what I need, which compiles, but it is written in C:

#include <stdio.h>
#include <malloc.h>

int* sorted_array(const size_t* size) {
    int* array = (int*)malloc(sizeof(int) * *size);
    for (size_t i = 0; i < *size; i++)
        array[i] = i;
    return array;
}

int main(void) {

    const size_t size = 1000;
    int* array = sorted_array(&size);

    return 0;
}

I will code it to do some sorts right after. I would appreciate it if you answered my questions and recode my beginner Zig tries.

like image 839
varikoz272 Avatar asked Oct 15 '25 19:10

varikoz272


1 Answers

Are you sure you want to use arrays? Zig arrays are pretty much the same as C arrays, the size must be known at compile time. But your C code dynamically allocates memory and returns a pointer to it, Zig provides a nice abstraction for this called slices. A slice is a many-item pointer to memory plus a length.

The Zig function equivalent for your C code would look like this:

fn create_sorted_array(allocator: std.mem.Allocator, len: *const usize) ![]i32 {
    const array = try allocator.alloc(i32, len.*);
    for (array, 0..) |*item, i| {
        item.* = @intCast(i);
    }
    return array;
}

As i know Zig has no hidden control and memory allocation, so if i pass an array as an argument will compiler clone it as it does with ints (as it should), or will it create a pointer as in C or Java?

Memory is always copied, but slices contain a pointer, the memory it points to is not copied.

Can functions return an array? If they can, do i need const or comptime as a length value?

Yes, the length must be comptime (known at compile time).

If i need to pass a pointer to array (or its address) how do i declare it, extract a value from it?

The declaration and use is no different from any other pointer (*[xxx]i32 to declare, pointer.* to dereference), but it can be inconvenient that the length must be known at compile time. Slices are much more convenient here, don't even have to use a pointer to a slice (although you can).

If i pass &size compiler says that function expects *usize not const *usize

Use *const usize. You don't need the size to be mutable.

but i cant rewrite it to const length: *usize because length should be comptime.

This seems to work, although it doesn't make much sense to me (a pointer known at compile time?):

fn sorted(comptime len: *const usize) [len.*]i32 {
    const array: [len.*]i32 = undefined;
    // ...
    return array;
}
like image 78
sigod Avatar answered Oct 18 '25 13:10

sigod



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!