# Primitive Types

### Primitive Types

Every value in a Zig program has a type.

A type tells the compiler what kind of value something is and what operations are allowed on it.

For example:

```zig
const age = 30;
```

The value `30` is an integer.

```zig
const price = 19.99;
```

The value `19.99` is a floating-point number.

```zig
const enabled = true;
```

The value `true` is a boolean.

These basic built-in types are called primitive types.

Primitive types are the foundation of the language. More complex types such as arrays, structs, slices, and unions are built from them.

#### Integer Types

Integers are whole numbers.

Examples:

```text
0
1
42
-10
1000000
```

Zig has many integer types because low-level programming often requires exact control over size and memory layout.

Common integer types:

| Type | Meaning | Size |
|---|---|---|
| `i8` | signed integer | 8 bits |
| `u8` | unsigned integer | 8 bits |
| `i16` | signed integer | 16 bits |
| `u16` | unsigned integer | 16 bits |
| `i32` | signed integer | 32 bits |
| `u32` | unsigned integer | 32 bits |
| `i64` | signed integer | 64 bits |
| `u64` | unsigned integer | 64 bits |
| `isize` | signed pointer-sized integer | platform dependent |
| `usize` | unsigned pointer-sized integer | platform dependent |

The letter meanings are:

| Prefix | Meaning |
|---|---|
| `i` | signed integer |
| `u` | unsigned integer |

Signed integers can store negative values:

```zig
const temperature: i32 = -10;
```

Unsigned integers cannot:

```zig
const count: u32 = 100;
```

This is invalid:

```zig
const value: u32 = -5; // error
```

#### Integer Ranges

The number of bits controls the range of values.

An 8-bit unsigned integer:

```zig
u8
```

can store:

```text
0 to 255
```

A signed 8-bit integer:

```zig
i8
```

can store:

```text
-128 to 127
```

Larger integer types can store larger numbers.

#### Why Exact Sizes Matter

In many high-level languages, programmers rarely think about memory size.

In Zig, exact sizes are important because Zig is designed for systems programming.

Examples:

- network protocols
- binary file formats
- operating systems
- embedded devices
- graphics programming

Suppose a file format says:

```text
this field is exactly 4 bytes
```

Then `u32` is appropriate.

If a protocol says:

```text
this value uses 1 byte
```

Then `u8` is appropriate.

Zig makes these details explicit.

#### Floating-Point Types

Floating-point numbers store decimal values.

Examples:

```zig
const pi = 3.14159;
const temperature = -2.5;
```

Common floating-point types:

| Type | Size |
|---|---|
| `f16` | 16 bits |
| `f32` | 32 bits |
| `f64` | 64 bits |
| `f80` | 80 bits |
| `f128` | 128 bits |

The most common are:

```zig
f32
f64
```

`f64` is commonly used because it gives better precision.

Example:

```zig
const price: f64 = 19.99;
```

#### Floating-Point Precision

Floating-point numbers are approximations.

This surprises many beginners.

For example:

```zig
const x: f64 = 0.1 + 0.2;
```

You might expect exactly:

```text
0.3
```

But internally, floating-point values are stored in binary approximations.

This is normal in nearly all programming languages.

Because of this, direct equality checks with floats should be used carefully.

#### Boolean Type

A boolean stores either:

```text
true
false
```

The type is:

```zig
bool
```

Example:

```zig
const is_admin: bool = true;
const finished: bool = false;
```

Booleans are commonly used with conditions:

```zig
if (is_admin) {
    // allowed
}
```

#### Character Data

Zig does not have a separate character type like some languages.

Instead, character values are usually represented with integers.

Example:

```zig
const letter: u8 = 'A';
```

The character `'A'` is stored as its ASCII numeric value.

```text
65
```

You can print it as a character:

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

pub fn main() void {
    const letter: u8 = 'A';

    std.debug.print("{c}\n", .{letter});
}
```

Output:

```text
A
```

The `{c}` formatter means:

```text
print as character
```

#### Void Type

The type `void` means “no value.”

Example:

```zig
pub fn main() void {

}
```

The `main` function returns nothing.

A function returning `void` performs actions rather than producing a value.

#### The `noreturn` Type

Some code never returns.

Example:

```zig
@panic("fatal error");
```

A panic stops the program completely.

Functions that never return use the type:

```zig
noreturn
```

This helps the compiler reason about control flow.

#### The `anyopaque` Type

Zig sometimes needs to work with raw unknown data.

The type:

```zig
anyopaque
```

represents opaque memory whose structure is unknown.

This is common in C interoperability and low-level APIs.

Beginners usually do not need this immediately, but you will see it later in systems code.

#### Type Annotation

You can explicitly write a type:

```zig
const age: u8 = 30;
```

Syntax:

```zig
name: Type
```

Examples:

```zig
const enabled: bool = true;
const score: i32 = 100;
const pi: f64 = 3.14;
```

#### Type Inference

Often Zig can infer the type automatically.

```zig
const score = 100;
const pi = 3.14;
```

This is convenient for local values.

But explicit types are still useful when:

- exact size matters
- APIs require a specific type
- clarity is important
- interfacing with hardware or C

#### Printing Different Primitive Types

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

pub fn main() void {
    const age: u8 = 25;
    const price: f64 = 19.99;
    const active: bool = true;
    const letter: u8 = 'Z';

    std.debug.print("Age: {}\n", .{age});
    std.debug.print("Price: {}\n", .{price});
    std.debug.print("Active: {}\n", .{active});
    std.debug.print("Letter: {c}\n", .{letter});
}
```

Output:

```text
Age: 25
Price: 19.99
Active: true
Letter: Z
```

#### Choosing the Right Type

Good Zig programmers choose types carefully.

Examples:

| Situation | Good Type |
|---|---|
| byte data | `u8` |
| file size | `usize` |
| negative temperatures | `i32` |
| decimal prices | `f64` |
| true/false state | `bool` |

Choosing correct types improves:

- memory efficiency
- correctness
- API clarity
- compiler checks
- portability

#### Primitive Types Are the Foundation

Almost everything in Zig eventually builds on primitive types.

Arrays contain primitive values.

Struct fields often use primitive types.

Pointers point to primitive data.

Binary formats are built from primitive types.

Memory layouts depend on primitive types.

If you understand primitive types clearly, the rest of the language becomes much easier to understand.

