Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function. However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this function used, examine closely - it may be a code smell. Zero initializes the type. This can be used to zero-initialize any type for which it makes sense. Structs will be initialized recursively.
pub fn zeroes(comptime T: type) T
pub fn zeroes(comptime T: type) T {
switch (@typeInfo(T)) {
.comptime_int, .int, .comptime_float, .float => {
return @as(T, 0);
},
.@"enum" => {
return @as(T, @fromBackingInt(@intCast(0)));
},
.void => {
return {};
},
.bool => {
return false;
},
.optional, .null => {
return null;
},
.@"struct" => |struct_info| {
if (@sizeOf(T) == 0) return undefined;
if (struct_info.layout == .@"extern") {
var item: T = undefined;
@memset(asBytes(&item), 0);
return item;
} else {
var structure: T = undefined;
inline for (
struct_info.field_names,
struct_info.field_types,
struct_info.field_attrs,
) |field_name, field_type, field_attrs| {
if (!field_attrs.@"comptime") {
@field(structure, field_name) = zeroes(field_type);
}
}
return structure;
}
},
.pointer => |ptr_info| {
switch (ptr_info.size) {
.slice => {
if (ptr_info.sentinel()) |sentinel| {
if (ptr_info.child == u8 and sentinel == 0) {
return ""; // A special case for the most common use-case: null-terminated strings.
}
@compileError("Can't set a sentinel slice to zero. This would require allocating memory.");
} else {
return &[_]ptr_info.child{};
}
},
.c => {
return null;
},
.one, .many => {
if (ptr_info.attrs.@"allowzero") return @ptrFromInt(0);
@compileError("Only nullable and allowzero pointers can be set to zero.");
},
}
},
.array => |info| {
return @splat(zeroes(info.child));
},
.vector => |info| {
return @splat(zeroes(info.child));
},
.@"union" => |info| {
if (info.layout == .@"extern") {
var item: T = undefined;
@memset(asBytes(&item), 0);
return item;
}
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
},
.enum_literal,
.error_union,
.error_set,
.@"fn",
.type,
.noreturn,
.undefined,
.@"opaque",
.spirv,
.frame,
.@"anyframe",
=> {
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
},
}
}