# Improving on \[\*c\]u8 when calling a C function that allocates a string?

**URL:** <https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489>\
**Category:** Help\
**Created:** [December 17, 2023, 2:08pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489 "2023-12-17T14:08:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mtlynch](https://ziggit.dev/user_avatar/ziggit.dev/mtlynch/32/1254_2.png) [@mtlynch](https://ziggit.dev/u/mtlynch)\
**Post date:** [December 17, 2023, 2:08pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/1 "2023-12-17T14:08:08Z")

</div>

Hi All, I’m a Zig beginner, and I’ve been [learning about using Zig](https://mtlynch.io/tags/zig/) to maintain C code.

I’m stuck on a typing issue, and I’m wondering if anyone can help.

I have a C function whose signature looks like this:

```c
void foo(char** c);

```

The function allocates and populates a null-terminated string, and the caller is responsible for freeing the memory.

I can call the function from Zig like this:

```zig
const std = @import("std");

const lib = @cImport({
    @cInclude("foo.c");
});

pub fn main() !void {
    var x: [*c]u8 = null;
    lib.foo(&x);
    std.c.free(x);
}

```

But I’d like to avoid the `[*c]u8` type, as I know that the output parameter from C is a many-item, null-terminated pointer.

My intuition is to define the type like this:

```zig
    var x: [*:0]u8 = undefined;
    lib.foo(&x);

```

But that gives me a compilation error:

```plaintext
error: expected type '[*c][*c]u8', found '*[*:0]u8'

```

I’ve tried a few different variations, but the Zig compiler rejects all of them.

Am I missing a more obvious type here?

---

<div class="post-metadata">

**Author:** ![Luke](https://ziggit.dev/letter_avatar_proxy/v4/letter/l/7ab992/32.png) [@Luke](https://ziggit.dev/u/Luke)\
**Post date:** [December 17, 2023, 2:12pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/2 "2023-12-17T14:12:54Z")

</div>

Maybe something like this:

```zig
[*:null]?[*:0]const u8

```

There was a related discussion on this recently: [Null terminated array of strings from C function - #4 by castholm](https://ziggit.dev/t/null-terminated-array-of-strings-from-c-function/2459/4)

---

<div class="post-metadata">

**Author:** ![mtlynch](https://ziggit.dev/user_avatar/ziggit.dev/mtlynch/32/1254_2.png) [@mtlynch](https://ziggit.dev/u/mtlynch)\
**Post date:** [December 17, 2023, 2:18pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/3 "2023-12-17T14:18:13Z")

</div>

Thanks for the suggestion!

That unfortunately doesn’t compile either:

```zig
    var x: [*:null]?[*:0]const u8 = undefined;
    lib.foo(&x);

```

```plaintext
 error: expected type '[*c][*c]u8', found '[*:null]?[*:0]const u8

```

I think the issue is that in the other thread, the user was working with an array of strings, whereas in this case, the `foo` function just populates a single string.

---

<div class="post-metadata">

**Author:** ![Luke](https://ziggit.dev/letter_avatar_proxy/v4/letter/l/7ab992/32.png) [@Luke](https://ziggit.dev/u/Luke)\
**Post date:** [December 17, 2023, 2:34pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/4 "2023-12-17T14:34:42Z")

</div>

Ok, what about then?:

```zig
    var x: ?[*:0]u8 = null;

```

---

<div class="post-metadata">

**Author:** ![LucasSantos91](https://ziggit.dev/user_avatar/ziggit.dev/lucassantos91/32/440_2.png) [@LucasSantos91](https://ziggit.dev/u/LucasSantos91)\
**Post date:** [December 17, 2023, 2:47pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/5 "2023-12-17T14:47:06Z")

</div>

Your type is correct.

```zig
var x: [*:0]u8 = undefined;
lib.foo(@ptrCast(&x));

```

---

<div class="post-metadata">

**Author:** ![mtlynch](https://ziggit.dev/user_avatar/ziggit.dev/mtlynch/32/1254_2.png) [@mtlynch](https://ziggit.dev/u/mtlynch)\
**Post date:** [December 17, 2023, 2:49pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/6 "2023-12-17T14:49:21Z")

</div>

> [@Luke](#):
>
> Ok, what about then?:
> 
> ` var x: ?[*:0]u8 = null;`

Ah, that did it. Thanks so much!

---

<div class="post-metadata">

**Author:** ![mtlynch](https://ziggit.dev/user_avatar/ziggit.dev/mtlynch/32/1254_2.png) [@mtlynch](https://ziggit.dev/u/mtlynch)\
**Post date:** [December 17, 2023, 2:50pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/7 "2023-12-17T14:50:12Z")

</div>

> [@LucasSantos91](#):
>
> Your type is correct.
> 
> ```zig
> var x: [*:0]u8 = undefined;
> lib.foo(@ptrCast(&x));
> 
> ```

Hmm, that gives me a segfault:

```bash
$ zig build run
Segmentation fault at address 0x0
???:?:?: 0x7ffff7e72075 in ??? (libc.so.6)
Unwind information for `libc.so.6:0x7ffff7e72075` was not available, trace may be incomplete

```

---

<div class="post-metadata">

**Author:** ![LucasSantos91](https://ziggit.dev/user_avatar/ziggit.dev/lucassantos91/32/440_2.png) [@LucasSantos91](https://ziggit.dev/u/LucasSantos91)\
**Post date:** [December 17, 2023, 2:53pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/8 "2023-12-17T14:53:39Z")

</div>

Well, that’s weird. At least you already have a solution.

---

<div class="post-metadata">

**Author:** ![permutationlock](https://ziggit.dev/user_avatar/ziggit.dev/permutationlock/32/9958_2.png) [@permutationlock](https://ziggit.dev/u/permutationlock)\
**Post date:** [December 17, 2023, 3:36pm UTC](https://ziggit.dev/t/improving-on-c-u8-when-calling-a-c-function-that-allocates-a-string/2489/9 "2023-12-17T15:36:07Z")

</div>

> [@mtlynch](#):
>
> ```zig
> var x: [*:0]u8 = undefined;
> lib.foo(&x);
> 
> ```
> 
> But that gives me a compilation error:
> 
> `error: expected type '[*c][*c]u8', found '*[*:0]u8'`

I ran into this recently too. The issue is that if `x: ?*[*:0]u8` was allowed to coerce to `y: [*c][*c]u8 = x`, then the type system would have to allow `y.* = null`, violating the guarantee that `x.?.*` is not null. So you have to add an extra optional `x: ?*?[*:0]u8`.

It seems that this is a limitation you have to live with when using `@cImport`, and to get the “correct” types you need to manually declare the signature of `foo` (which I generally prefer over `@cImport` anyway).

```zig
extern fn foo(c: ?*[*:0]u8) void;

```
