# `@memcpy`

### `@memcpy`

`@memcpy` copies bytes from one memory region to another.

The name means “memory copy.”

You use it when you already have destination memory and source memory, and you want the destination to receive the source bytes.

```zig
@memcpy(destination, source);
```

The destination and source are usually slices.

#### A Simple Example

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

pub fn main() void {
    var dst = [_]u8{ 0, 0, 0, 0 };
    const src = [_]u8{ 1, 2, 3, 4 };

    @memcpy(&dst, &src);

    std.debug.print("{any}\n", .{dst});
}
```

Output:

```text
{ 1, 2, 3, 4 }
```

The bytes from `src` were copied into `dst`.

#### Destination Must Be Mutable

The destination must allow writing.

This works:

```zig
var dst = [_]u8{ 0, 0, 0 };
const src = [_]u8{ 1, 2, 3 };

@memcpy(&dst, &src);
```

This does not work:

```zig
const dst = [_]u8{ 0, 0, 0 };
const src = [_]u8{ 1, 2, 3 };

@memcpy(&dst, &src);
```

The destination is `const`, so Zig will not let you write into it.

#### Source and Destination Lengths Must Match

For slices, the destination and source must have the same length.

```zig
var dst = [_]u8{ 0, 0, 0 };
const src = [_]u8{ 1, 2, 3 };

@memcpy(&dst, &src);
```

Both have length `3`.

This is wrong:

```zig
var dst = [_]u8{ 0, 0, 0 };
const src = [_]u8{ 1, 2, 3, 4 };

@memcpy(&dst, &src);
```

The destination has 3 bytes. The source has 4 bytes. Zig rejects this or detects the mismatch.

For dynamic slices, make the lengths explicit:

```zig
@memcpy(dst[0..src.len], src);
```

This says: copy exactly `src.len` items.

#### Copying Part of a Buffer

Suppose you have a larger buffer:

```zig
var buffer = [_]u8{0} ** 16;
const hello = "hello";
```

You can copy the string into the first part of the buffer:

```zig
@memcpy(buffer[0..hello.len], hello);
```

Full example:

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

pub fn main() void {
    var buffer = [_]u8{0} ** 16;
    const text = "hello";

    @memcpy(buffer[0..text.len], text);

    std.debug.print("{s}\n", .{buffer[0..text.len]});
}
```

Output:

```text
hello
```

The buffer has 16 bytes, but only the first 5 bytes receive the text.

#### `@memcpy` Copies Elements

Although the name says “memory,” `@memcpy` works with element slices.

For byte slices, it copies bytes.

For `u32` slices, it copies `u32` elements.

```zig
var dst = [_]u32{ 0, 0, 0 };
const src = [_]u32{ 10, 20, 30 };

@memcpy(&dst, &src);
```

This copies 3 `u32` values.

The total number of copied bytes is:

```text
3 * @sizeOf(u32)
```

So on common targets, that is:

```text
3 * 4 = 12 bytes
```

But you usually think of it as copying three elements.

#### Source and Destination Must Not Overlap

`@memcpy` is for non-overlapping memory.

This is important.

If the source and destination refer to overlapping parts of the same buffer, the result is not safe to rely on.

Example of overlapping memory:

```zig
var data = [_]u8{ 1, 2, 3, 4, 5 };

@memcpy(data[1..5], data[0..4]);
```

The source is:

```text
data[0..4] = 1, 2, 3, 4
```

The destination is:

```text
data[1..5] = 2, 3, 4, 5
```

These ranges overlap.

Use the standard library helper for overlapping copies when needed, such as `std.mem.copyForwards` or `std.mem.copyBackwards`, depending on direction.

#### `@memcpy` vs Assignment

For fixed-size arrays, simple assignment may be clearer.

```zig
var a = [_]u8{ 1, 2, 3 };
var b = [_]u8{ 0, 0, 0 };

b = a;
```

This copies the array value.

For slices and buffers, `@memcpy` is useful because you are copying into existing memory.

```zig
@memcpy(dst, src);
```

A good rule:

Use assignment for whole values.

Use `@memcpy` for copying into a memory region.

#### `@memcpy` Does Not Allocate

`@memcpy` only copies into memory that already exists.

This is wrong thinking:

```zig
var dst: []u8 = undefined;
@memcpy(dst, "hello");
```

The slice `dst` does not own valid memory here. It has no real buffer.

You need actual storage:

```zig
var buffer = [_]u8{0} ** 5;
@memcpy(&buffer, "hello");
```

Or you need allocated memory:

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    const src = "hello";
    const dst = try allocator.alloc(u8, src.len);
    defer allocator.free(dst);

    @memcpy(dst, src);
}
```

The allocator creates memory. `@memcpy` fills it.

#### Copying Struct Bytes

Sometimes you want to copy the raw bytes of a value.

For ordinary Zig code, prefer normal assignment:

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

var a = Point{ .x = 1, .y = 2 };
var b = a;
```

This is clear and type-safe.

Only use byte-level copying when you are working with representation-level code, such as serialization, binary formats, or low-level APIs.

#### `@memcpy` Is Low-Level

`@memcpy` is not complicated, but it is low-level.

It assumes you already know:

the destination memory is valid

the destination is writable

the source memory is valid

the lengths match

the regions do not overlap

Zig checks what it can, but your design still matters.

#### A Common Pattern

This pattern appears often:

```zig
fn writePrefix(buffer: []u8, prefix: []const u8) void {
    @memcpy(buffer[0..prefix.len], prefix);
}
```

But this function has a hidden assumption: `buffer.len >= prefix.len`.

A safer version checks it:

```zig
fn writePrefix(buffer: []u8, prefix: []const u8) !void {
    if (buffer.len < prefix.len) return error.BufferTooSmall;

    @memcpy(buffer[0..prefix.len], prefix);
}
```

Now the function says what can go wrong.

#### Key Idea

`@memcpy(destination, source)` copies memory from `source` into `destination`.

It does not allocate.

It does not resize.

It should not be used for overlapping regions.

Use it when you already have valid destination memory and want to copy elements from a source slice into it.

