077_sentinels2.zig 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. //
  2. // ------------------------------------------------------------
  3. // TOP SECRET TOP SECRET TOP SECRET TOP SECRET TOP SECRET
  4. // ------------------------------------------------------------
  5. //
  6. // Are you ready for the THE TRUTH about Zig string literals?
  7. //
  8. // Here it is:
  9. //
  10. // @TypeOf("foo") == *const [3:0]u8
  11. //
  12. // Which means a string literal is a "constant pointer to a
  13. // zero-terminated (null-terminated) fixed-size array of u8".
  14. //
  15. // Now you know. You've earned it. Welcome to the secret club!
  16. //
  17. // ------------------------------------------------------------
  18. //
  19. // Why do we bother using a zero/null sentinel to terminate
  20. // strings in Zig when we already have a known length?
  21. //
  22. // Versatility! Zig strings are compatible with C strings (which
  23. // are null-terminated) AND can be coerced to a variety of other
  24. // Zig types:
  25. //
  26. // const a: [5]u8 = "array".*;
  27. // const b: *const [16]u8 = "pointer to array";
  28. // const c: []const u8 = "slice";
  29. // const d: [:0]const u8 = "slice with sentinel";
  30. // const e: [*:0]const u8 = "many-item pointer with sentinel";
  31. // const f: [*]const u8 = "many-item pointer";
  32. //
  33. // All but 'f' may be printed. (A many-item pointer without a
  34. // sentinel is not safe to print because we don't know where it
  35. // ends!)
  36. //
  37. const print = @import("std").debug.print;
  38. const WeirdContainer = struct {
  39. data: [*]const u8,
  40. length: usize,
  41. };
  42. pub fn main() void {
  43. // WeirdContainer is an awkward way to house a string.
  44. //
  45. // Being a many-item pointer (with no sentinel termination),
  46. // the 'data' field "loses" the length information AND the
  47. // sentinel termination of the string literal "Weird Data!".
  48. //
  49. // Luckily, the 'length' field makes it possible to still
  50. // work with this value.
  51. const foo = WeirdContainer {
  52. .data = "Weird Data!",
  53. .length = 11,
  54. };
  55. // How do we get a printable value from 'foo'? One way is to
  56. // turn it into something with a known length. We do have a
  57. // length... You've actually solved this problem before!
  58. //
  59. // Here's a big hint: do you remember how to take a slice?
  60. const printable = ???;
  61. print("{s}\n", .{printable});
  62. }