278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
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.");
},
}
}
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.