# ABI and Layout

### ABI and Layout

A C program and a Zig program can share data only when both sides agree on layout.

Layout means the exact order, size, alignment, and padding of values in memory. C code does not see Zig types. It sees bytes at addresses. If the bytes do not have the shape C expects, the program is wrong.

For simple integer and floating-point values, use C-compatible types:

```zig
c_char
c_short
c_int
c_long
c_longlong
c_float
c_double
```

These names follow the target C ABI.

For structs, use `extern struct`.

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

This matches the usual C declaration:

```c
struct Point {
    int x;
    int y;
};
```

A normal Zig struct should not be passed to C as a C struct.

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

Zig may choose a layout that is useful for Zig. C cannot rely on it.

The same rule applies to unions.

```zig
const Number = extern union {
    i: c_int,
    d: c_double,
};
```

This matches:

```c
union Number {
    int i;
    double d;
};
```

For packed binary formats, use `packed struct`, but do not confuse it with C layout. Packed layout is for bit-level representation. C struct layout is ABI layout.

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

This is useful for exact bits. It is not a general replacement for `extern struct`.

Function layout is controlled by the calling convention.

```zig
extern "c" fn puts(s: [*:0]const u8) c_int;
```

The `"c"` convention tells Zig to call the function as C would call it on the target platform.

When exporting a function to C, keep the boundary plain:

```zig
export fn scale(x: c_double, factor: c_double) c_double {
    return x * factor;
}
```

Avoid Zig-only parameter types in exported functions:

```zig
export fn bad(xs: []const u8) void {
    _ = xs;
}
```

A slice has Zig layout. C does not know it. Use pointer plus length:

```zig
export fn good(ptr: [*]const u8, len: usize) void {
    const xs = ptr[0..len];
    _ = xs;
}
```

At the boundary, prefer boring types.

Inside Zig, convert them into safer Zig forms. Keep C layout at the edge.

