mirror of
https://codeberg.org/ziglings/exercises.git
synced 2026-06-08 07:50:00 +00:00
Insert space for additional async exercises
This commit is contained in:
78
exercises/115_packed2.zig
Normal file
78
exercises/115_packed2.zig
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// We've already learned about switch statements in exercises 030, 031 and 108.
|
||||
// They also work with packed containers:
|
||||
|
||||
const S = packed struct(u2) {
|
||||
a: bool,
|
||||
b: i1,
|
||||
};
|
||||
|
||||
// Try to make it compile without adding an `else` prong!
|
||||
|
||||
comptime {
|
||||
const s: S = .{ .a = true, .b = -1 };
|
||||
switch (s) {
|
||||
.{ .a = true, .b = -1 } => {}, // ok!
|
||||
.{ .a = true, .b = ??? },
|
||||
.{ .a = ???, .b = 0 },
|
||||
.{ .a = ???, .b = ??? },
|
||||
=> @compileError("We don't want to end up here!"),
|
||||
}
|
||||
}
|
||||
|
||||
// As we can see, switching on packed structs is pretty straightforward.
|
||||
// When switching on packed unions however, we'll realize that a packed
|
||||
// union never keeps track of its active tag, not even in debug mode! This
|
||||
// means that packed unions compare solely by their bit pattern (again, just
|
||||
// like integers).
|
||||
|
||||
const U = packed union(u2) {
|
||||
a: u2,
|
||||
b: i2,
|
||||
};
|
||||
|
||||
// Find and remove the duplicate case!
|
||||
|
||||
comptime {
|
||||
const u: U = .{ .a = 3 };
|
||||
switch (u) {
|
||||
.{ .a = 3 } => {}, // ok!
|
||||
.{ .a = 2 },
|
||||
.{ .b = 1 },
|
||||
.{ .b = -1 },
|
||||
.{ .a = 0 },
|
||||
=> @compileError("We don't want to end up here!"),
|
||||
}
|
||||
}
|
||||
|
||||
// Since packed unions don't have the concept of an active tag, it's always legal
|
||||
// to access any of their fields. This can be useful to view the same data from
|
||||
// different perspectives seamlessly.
|
||||
//
|
||||
// Try to make the float below negative:
|
||||
|
||||
/// IEEE 754 half precision float
|
||||
const Float = packed union(u16) {
|
||||
value: f16,
|
||||
bits: packed struct(u16) {
|
||||
mantissa: u10,
|
||||
exponent: u5,
|
||||
sign: u1,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn main() void {
|
||||
// Reminder: if the sign bit of a float is set, the number is negative!
|
||||
|
||||
var number: Float = .{ .value = 2.34 };
|
||||
number.bits.??? = ???;
|
||||
if (number.value != -2.34) {
|
||||
std.debug.print("Make it negative!\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
// This concludes our introduction to packed containers. The next time you need
|
||||
// control over individual bits, keep them in mind as a potent alternative!
|
||||
//
|
||||
|
||||
const std = @import("std");
|
||||
Reference in New Issue
Block a user