# Data Layout

### Data Layout

A struct is not only a list of fields. It also has a layout in memory.

For a normal struct, Zig chooses a layout suitable for the target machine.

```zig
const Point = struct {
    x: i32,
    y: i32,
};
```

This type contains two `i32` fields. On most targets, each `i32` uses 4 bytes, so the struct uses 8 bytes.

```zig
const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() void {
    std.debug.print("{d}\n", .{@sizeOf(Point)});
}
```

The output is usually:

```text
8
```

`@sizeOf(T)` gives the size of a type in bytes.

Alignment also matters.

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("u8  size = {d}, align = {d}\n", .{
        @sizeOf(u8),
        @alignOf(u8),
    });

    std.debug.print("u32 size = {d}, align = {d}\n", .{
        @sizeOf(u32),
        @alignOf(u32),
    });
}
```

A value's alignment is the address boundary where the target expects that value to be placed. A `u32` often has alignment 4. That means its address should be divisible by 4.

Padding is added to satisfy alignment.

```zig
const A = struct {
    a: u8,
    b: u32,
};
```

This struct has one byte field followed by a four byte field. The compiler may place padding between them so that `b` is aligned.

On a common 64-bit target, this type often has size 8, not 5.

```zig
const std = @import("std");

const A = struct {
    a: u8,
    b: u32,
};

pub fn main() void {
    std.debug.print("size = {d}\n", .{@sizeOf(A)});
    std.debug.print("align = {d}\n", .{@alignOf(A)});
}
```

A different field order may use less space.

```zig
const B = struct {
    b: u32,
    a: u8,
};
```

This still may have padding at the end, but there is no need for padding before `b`.

Do not rely on field order or padding for ordinary structs when talking to C, files, or hardware. A normal Zig struct is for Zig data. Its layout is chosen by the compiler.

When layout must match C, use `extern struct`.

```zig
const CPoint = extern struct {
    x: c_int,
    y: c_int,
};
```

An `extern struct` has a layout compatible with the C ABI for the target.

Use it at C boundaries.

```zig
extern fn draw_point(p: CPoint) void;
```

When layout must match exact bits, use `packed struct`.

```zig
const Register = packed struct {
    carry: bool,
    zero: bool,
    interrupt: bool,
    decimal: bool,
    brk: bool,
    unused: bool,
    overflow: bool,
    negative: bool,
};
```

The three common struct forms are:

| Form | Purpose |
|---|---|
| `struct` | Ordinary Zig data |
| `extern struct` | C ABI layout |
| `packed struct` | Exact bit layout |

A normal struct is the right default.

```zig
const User = struct {
    id: u64,
    name: []const u8,
    active: bool,
};
```

This says what the program means. It does not promise a file format or a C layout.

Use `extern struct` when another language must see the same layout.

```zig
const Stat = extern struct {
    size: c_long,
    mode: c_uint,
};
```

Use `packed struct` when individual bits have names.

```zig
const Flags = packed struct {
    read: bool,
    write: bool,
    execute: bool,
};
```

The address of a field can be taken for normal structs.

```zig
var p = Point{
    .x = 1,
    .y = 2,
};

const xp = &p.x;
```

For packed structs, fields may not be addressable in the same way. A packed field can start at a bit offset that has no ordinary address. Read and write packed fields as values.

Data layout becomes important when the program crosses a boundary: C calls, system calls, binary files, network packets, memory-mapped registers, or disk formats.

Inside ordinary program code, prefer clear fields and simple types. Let the compiler choose the layout unless the layout is part of the contract.

Exercises.

7-25. Use `@sizeOf` to print the size of a struct with fields `u8` and `u32`.

7-26. Change the field order and compare the result.

7-27. Use `@alignOf` on `u8`, `u16`, `u32`, and `u64`.

7-28. Write one normal struct, one `extern struct`, and one `packed struct`, each with a short comment saying why that form was chosen.

