# Exercises

### Exercises

1. Write a function `increment` that takes `*i32` and adds 1 to the pointed-to value.

```zig
fn increment(n: *i32) void {
    // ...
}
```

2. Write a function `swap` that exchanges two integers through pointers.

```zig
fn swap(a: *i32, b: *i32) void {
    // ...
}
```

3. Declare a constant integer, take its address, and observe the type of the pointer.

```zig
const x: i32 = 10;
const p = &x;
```

4. Try to modify a value through a `*const i32` pointer. Read the compiler error.

5. Write a function `doubleAll` that doubles every element in a mutable slice.

```zig
fn doubleAll(items: []i32) void {
    // ...
}
```

6. Write a function `countZeroes` that counts how many elements in `[]const i32` are zero.

7. Create an array of five integers. Take a slice of the middle three elements and print them.

8. Rewrite the previous exercise using a many-item pointer and a separate length.

9. Write a function that returns the largest value in a slice.

```zig
fn max(items: []const i32) i32 {
    // ...
}
```

10. Write a function that fills a slice with a chosen byte.

```zig
fn fill(items: []u8, value: u8) void {
    // ...
}
```

11. Create a sentinel-terminated string pointer.

```zig
const name: [*:0]const u8 = "zig";
```

Write a function that counts bytes until the zero sentinel is reached.

12. Print the alignment of these types:

```zig
u8
u16
u32
u64
f32
f64
```

Use `@alignOf`.

13. Create a byte array and interpret four bytes as a little-endian integer using `std.mem.readInt`.

14. Declare a weakly aligned pointer.

```zig
*align(1) i32
```

Try assigning it directly to `*i32`. Read the compiler error. Then use `@alignCast`.

15. Write a function that takes a slice and reverses its elements in place.

```zig
fn reverse(items: []i32) void {
    // ...
}
```

16. Allocate an array dynamically with an allocator, assign values, print them, and free the memory.

17. Write a function that allocates and returns a slice of ten integers.

```zig
fn makeNumbers(
    allocator: std.mem.Allocator,
) ![]i32 {
    // ...
}
```

Free the slice in the caller.

18. Write a function that incorrectly returns a pointer to a local variable.

```zig
fn bad() *i32 {
    // ...
}
```

Explain why the returned pointer is invalid.

19. Define a struct containing a slice.

```zig
const Buffer = struct {
    data: []u8,
};
```

Write a method that sets every byte in the slice to zero.

20. Write a small string-copy function using slices.

```zig
fn copy(dst: []u8, src: []const u8) usize {
    // ...
}
```

Return the number of bytes copied.

21. Write a function using pointer arithmetic over a many-item pointer.

```zig
fn sumMany(ptr: [*]const i32, len: usize) i32 {
    // ...
}
```

Then rewrite it using a slice.

22. Explain the difference between these types:

```zig
*i32
*const i32
[*]i32
[]i32
[]const i32
?*i32
```

23. Explain the difference between ownership and access. Which values in this chapter own storage, and which merely refer to it?

24. Rewrite a pointer-based function to use ordinary value parameters instead. Compare the two versions.

25. Write a short note explaining when slices should be preferred over many-item pointers.

