# Zero Values and Initialization

### Zero Values and Initialization

Initialization means giving a value to something when it is created.

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

Here, `x` is initialized with `10`.

A value should usually be initialized immediately. This keeps the program simple. When a reader sees the name, they also see the value it starts with.

#### Zig Does Not Automatically Zero Everything

In some languages, variables may automatically start as zero, false, or empty.

Zig does not want you to depend on hidden initialization.

This is clear:

```zig
var count: usize = 0;
```

This is also clear:

```zig
const enabled: bool = false;
```

The starting value is visible in the code.

Zig prefers this style because systems programs need precise control. Sometimes you want zero. Sometimes you want `null`. Sometimes you want an empty array. Sometimes you want uninitialized memory for performance. These are different choices, so Zig makes you write the choice.

#### Zero Is a Real Value

Zero is not the same as `undefined`.

```zig
var x: i32 = 0;
```

This creates an integer with a meaningful value: zero.

```zig
var x: i32 = undefined;
```

This creates storage for an integer, but the value is not meaningful yet.

Use zero when zero is the correct starting value.

```zig
var total: i32 = 0;
var index: usize = 0;
var bytes_read: usize = 0;
```

These are good uses of zero. A sum often starts at zero. An index often starts at zero. A byte counter often starts at zero.

#### Boolean Initialization

A boolean should be initialized to either `true` or `false`.

```zig
var found: bool = false;
```

This is common when searching:

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

pub fn main() void {
    const numbers = [_]i32{ 10, 20, 30 };

    var found: bool = false;

    for (numbers) |n| {
        if (n == 20) {
            found = true;
            break;
        }
    }

    std.debug.print("found = {}\n", .{found});
}
```

Output:

```text
found = true
```

The initial value `false` means “we have not found it yet.”

#### Numeric Initialization

Numeric variables often start with `0`.

```zig
var sum: i32 = 0;
var count: usize = 0;
```

Example:

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

pub fn main() void {
    const numbers = [_]i32{ 3, 4, 5 };

    var sum: i32 = 0;

    for (numbers) |n| {
        sum += n;
    }

    std.debug.print("sum = {}\n", .{sum});
}
```

Output:

```text
sum = 12
```

The variable `sum` must have a real starting value because each loop step reads the old value before writing the new one.

This line:

```zig
sum += n;
```

means:

```zig
sum = sum + n;
```

So `sum` must already contain a valid number.

#### Arrays Filled with Zero

You can create an array filled with zeros.

```zig
var buffer = [_]u8{0} ** 64;
```

This creates an array of 64 bytes, each set to `0`.

The syntax:

```zig
[_]u8{0} ** 64
```

means “repeat this one-element array 64 times.”

A smaller example:

```zig
const numbers = [_]u8{0} ** 4;
```

This creates:

```text
0, 0, 0, 0
```

This is useful when you need predictable initial contents.

#### Arrays with Specific Values

You can also initialize each element manually.

```zig
const numbers = [_]i32{ 10, 20, 30 };
```

Zig infers the length. This array has type:

```zig
[3]i32
```

You can write the length explicitly too:

```zig
const numbers: [3]i32 = .{ 10, 20, 30 };
```

Both forms are common.

#### Struct Initialization

A struct value should be initialized by naming its fields.

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

const p = Point{
    .x = 10,
    .y = 20,
};
```

This creates a `Point` with `x = 10` and `y = 20`.

Complete example:

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

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

pub fn main() void {
    const p = Point{
        .x = 10,
        .y = 20,
    };

    std.debug.print("({}, {})\n", .{ p.x, p.y });
}
```

Output:

```text
(10, 20)
```

Field names make the code clear. You can see exactly which value belongs to which field.

#### Default Field Values

Struct fields can have default values.

```zig
const Config = struct {
    port: u16 = 8080,
    debug: bool = false,
};
```

Now you can create a value using the defaults:

```zig
const config = Config{};
```

This means:

```zig
const config = Config{
    .port = 8080,
    .debug = false,
};
```

You can also override one field:

```zig
const config = Config{
    .debug = true,
};
```

Then `port` uses its default value, and `debug` is set to `true`.

Complete example:

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

const Config = struct {
    port: u16 = 8080,
    debug: bool = false,
};

pub fn main() void {
    const config = Config{
        .debug = true,
    };

    std.debug.print("port = {}, debug = {}\n", .{
        config.port,
        config.debug,
    });
}
```

Output:

```text
port = 8080, debug = true
```

Defaults are useful for configuration structs, options, and values with common settings.

#### Optional Initialization

An optional value can contain either a value or `null`.

```zig
var maybe_number: ?i32 = null;
```

This means there is no integer right now.

Later, you can store an integer:

```zig
maybe_number = 42;
```

This is different from zero.

```zig
var a: ?i32 = null;
var b: ?i32 = 0;
```

`a` contains no integer.

`b` contains an integer, and that integer is zero.

That distinction is important. Zero is a value. `null` means no value.

#### Sentinel Values

Sometimes programs use a special value to mean “not found.”

For example:

```zig
const not_found: i32 = -1;
```

But in Zig, an optional is often clearer:

```zig
fn findNumber() ?usize {
    return null;
}
```

This says directly that the function may return an index, or may return no index.

Prefer optionals when “no value” is part of the meaning.

#### Initializing with a Function Call

A value can be initialized from a function result.

```zig
fn defaultPort() u16 {
    return 8080;
}

const port = defaultPort();
```

This is still initialization. The value is known after the function call returns.

Complete example:

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

fn square(x: i32) i32 {
    return x * x;
}

pub fn main() void {
    const result = square(7);

    std.debug.print("result = {}\n", .{result});
}
```

Output:

```text
result = 49
```

#### Initialization Before Use

The safest rule is simple: initialize before use.

This is correct:

```zig
var count: usize = 0;
count += 1;
```

This is wrong:

```zig
var count: usize = undefined;
count += 1;
```

Why? Because `count += 1` reads the old value of `count`. But the old value is undefined.

This would be valid:

```zig
var count: usize = undefined;
count = 0;
count += 1;
```

But it is worse than the simpler version:

```zig
var count: usize = 0;
count += 1;
```

Use the simple version.

#### Initialization and `const`

A `const` must be initialized when it is declared.

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

You cannot declare a constant and assign it later.

```zig
const x: i32; // invalid
x = 10;
```

This makes sense. A constant gets one value, and that value cannot change.

#### Initialization and `var`

A `var` also usually has an initializer.

```zig
var count: usize = 0;
```

When you need delayed initialization, you can use `undefined` with an explicit type:

```zig
var value: i32 = undefined;
value = 42;
```

But for beginner code, avoid this unless there is a clear reason.

#### A Complete Example

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

const Stats = struct {
    count: usize = 0,
    sum: i32 = 0,
};

pub fn main() void {
    const numbers = [_]i32{ 4, 8, 15, 16, 23, 42 };

    var stats = Stats{};

    for (numbers) |n| {
        stats.count += 1;
        stats.sum += n;
    }

    std.debug.print("count = {}, sum = {}\n", .{
        stats.count,
        stats.sum,
    });
}
```

Output:

```text
count = 6, sum = 108
```

The struct has default values:

```zig
const Stats = struct {
    count: usize = 0,
    sum: i32 = 0,
};
```

So this:

```zig
var stats = Stats{};
```

starts with:

```text
count = 0
sum = 0
```

That makes the loop safe, because both fields have real values before they are updated.

#### The Main Idea

Initialization is the act of giving storage a real value.

Use `0` when zero is meaningful. Use `false` when a boolean starts false. Use `null` when an optional has no value. Use default struct fields when a type has common starting values. Use `undefined` only when you will write a real value before reading it.

Clear initialization makes Zig code easier to read and harder to misuse.

