这看起来比它应该的要复杂(并且会复制?)。因此,我认为它们是兼容的C字符串,一个非常简单的转换如@as([*:0]const u8, buffer)就足够了?
问题在于[*:0]u8和[:0]u8之间存在差异:
- [*:0]u8是以0结尾的未知大小的指针。要确定其长度,您必须循环查找其结束位置。
- [:0]u8是包含指针和长度的切片。您可以将其视为struct {ptr: [*:0]u8, len: usize}。这使得使用它的代码能够立即知道它的长度,而无需循环遍历。
@pointerCast不需要将[*c]u8转换为[*:0]u8:
const std = @import("std");
test "convert c string to [*:0]u8" {
const c_string: [*c]const u8 = "some c string";
const as_ptr: [*:0]const u8 = c_string;
_ = as_ptr;
}
为了获得zig风格的字符串切片(
[]const u8
或
[:0]const u8
),你可以使用标准库函数
std.mem.span(ptr)。
const std = @import("std");
test "convert c string to zig string" {
const c_string: [*c]const u8 = "some c string";
const as_slice: [:0]const u8 = std.mem.span(c_string);
try std.testing.expectEqualStrings(as_slice, "some c string");
}
const buffer: [*c]u8 = callC();
const str = std.mem.span(@ptrCast([*:0]const u8, buffer));
Which looks more complicated than it should (and makes a copy??).
std.mem.span
不会复制字符串 - 除非你传递一个分配器,否则没有标准库函数会复制任何东西。
它所做的是计算字符串的长度,然后返回同一内存的切片,这次包括一个长度。
@ptrCast([*:0]const u8, buffer)
应该就足够了。但是为什么要使用指针,当你可以使用美妙的切片呢?然后只需要std.mem.span(buffer)
。 - sigod