aboutsummaryrefslogtreecommitdiff
path: root/exercises/077_sentinels2.zig
blob: fb8f13d843f8ba9f2089a0c9d5eb4b3dedc878e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//
// ------------------------------------------------------------
//  TOP SECRET  TOP SECRET  TOP SECRET  TOP SECRET  TOP SECRET
// ------------------------------------------------------------
//
// Are you ready for the THE TRUTH about Zig string literals?
//
// Here it is:
//
//     @TypeOf("foo") == *const [3:0]u8
//
// Which means a string literal is a "constant pointer to a
// zero-terminated (null-terminated) fixed-size array of u8".
//
// Now you know. You've earned it. Welcome to the secret club!
//
// ------------------------------------------------------------
//
// Why do we bother using a zero/null sentinel to terminate
// strings in Zig when we already have a known length?
//
// Versatility! Zig strings are compatible with C strings (which
// are null-terminated) AND can be coerced to a variety of other
// Zig types:
//
//     const a: [5]u8 = "array".*;
//     const b: *const [16]u8 = "pointer to array";
//     const c: []const u8 = "slice";
//     const d: [:0]const u8 = "slice with sentinel";
//     const e: [*:0]const u8 = "many-item pointer with sentinel";
//     const f: [*]const u8 = "many-item pointer";
//
// All but 'f' may be printed. (A many-item pointer without a
// sentinel is not safe to print because we don't know where it
// ends!)
//
const print = @import("std").debug.print;

const WeirdContainer = struct {
    data: [*]const u8,
    length: usize,
};

pub fn main() void {
    // WeirdContainer is an awkward way to house a string.
    //
    // Being a many-item pointer (with no sentinel termination),
    // the 'data' field "loses" the length information AND the
    // sentinel termination of the string literal "Weird Data!".
    //
    // Luckily, the 'length' field makes it possible to still
    // work with this value.
    const foo = WeirdContainer{
        .data = "Weird Data!",
        .length = 11,
    };

    // How do we get a printable value from 'foo'? One way is to
    // turn it into something with a known length. We do have a
    // length... You've actually solved this problem before!
    //
    // Here's a big hint: do you remember how to take a slice?
    const printable = ???;

    print("{s}\n", .{printable});
}