043_pointers5.zig 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. //
  2. // As with integers, you can pass a pointer to a struct when you
  3. // will wish to modify that struct. Pointers are also useful when
  4. // you need to store a reference to a struct (a "link" to it).
  5. //
  6. // const Vertex = struct{ x: u32, y: u32, z: u32 };
  7. //
  8. // var v1 = Vertex{ .x=3, .y=2, .z=5 };
  9. //
  10. // var pv: *Vertex = &v1; // <-- a pointer to our struct
  11. //
  12. // Note that you don't need to dereference the "pv" pointer to access
  13. // the struct's fields:
  14. //
  15. // YES: pv.x
  16. // NO: pv.*.x
  17. //
  18. // We can write functions that take pointers to structs as
  19. // arguments. This foo() function modifies struct v:
  20. //
  21. // fn foo(v: *Vertex) void {
  22. // v.x += 2;
  23. // v.y += 3;
  24. // v.z += 7;
  25. // }
  26. //
  27. // And call them like so:
  28. //
  29. // foo(&v1);
  30. //
  31. // Let's revisit our RPG example and make a printCharacter() function
  32. // that takes a Character by reference and prints it...*and*
  33. // prints a linked "mentor" Character, if there is one.
  34. //
  35. const std = @import("std");
  36. const Class = enum {
  37. wizard,
  38. thief,
  39. bard,
  40. warrior,
  41. };
  42. const Character = struct {
  43. class: Class,
  44. gold: u32,
  45. health: u8 = 100, // You can provide default values
  46. experience: u32,
  47. // I need to use the '?' here to allow for a null value. But
  48. // I don't explain it until later. Please don't tell anyone.
  49. mentor: ?*Character = null,
  50. };
  51. pub fn main() void {
  52. var mighty_krodor = Character{
  53. .class = Class.wizard,
  54. .gold = 10000,
  55. .experience = 2340,
  56. };
  57. var glorp = Character{ // Glorp!
  58. .class = Class.wizard,
  59. .gold = 10,
  60. .experience = 20,
  61. .mentor = &mighty_krodor, // Glorp's mentor is the Mighty Krodor
  62. };
  63. // FIX ME!
  64. // Please pass Glorp to printCharacter():
  65. printCharacter(???);
  66. }
  67. // Note how this function's "c" parameter is a pointer to a Character struct.
  68. fn printCharacter(c: *Character) void {
  69. // Here's something you haven't seen before: when switching an enum, you
  70. // don't have to write the full enum name. Zig understands that ".wizard"
  71. // means "Class.wizard" when we switch on a Class enum value:
  72. const class_name = switch (c.class) {
  73. .wizard => "Wizard",
  74. .thief => "Thief",
  75. .bard => "Bard",
  76. .warrior => "Warrior",
  77. };
  78. std.debug.print("{s} (G:{} H:{} XP:{})\n", .{
  79. class_name,
  80. c.gold,
  81. c.health,
  82. c.experience,
  83. });
  84. // Checking an "optional" value and capturing it will be
  85. // explained later (this pairs with the '?' mentioned above.)
  86. if (c.mentor) |mentor| {
  87. std.debug.print(" Mentor: ", .{});
  88. printCharacter(mentor);
  89. }
  90. }