Structures
// Named structure with no fields
Empty :: struct{};
// Named structure with three fields
Vector3 :: struct {
x: f32;
y: f32;
z: f32;
}
// Structures can be used as fields of other structures
Box :: struct {
position, dimension: Vector3;
}
x: struct{x, y: f32}; // Variable with anonymous structure with two fields
main :: proc() {
// Declare a `Vector3`
point := Vector3{1.2, -0.3, 7.4};
// Assign particular fields in a structure literal
another_point := Vector3{z = 1, x = 2, y = 3};
rect := Box {
position = Vector3{1, 4, 9},
dimension = Vector3{1, 2, 4},
};
// Accessing a struct member
fmt.println(rect.position.x);
// Assigning a value
rect.position.x = 123;
}
Memory layout
A structure's memory layout by default is arranged to minimize alignment padding (and thus its size).
A :: struct{x: u32; y: u8};
B :: struct{y: u8; x: u32};
compile_assert(size_of(A) == size_of(B));
This differs from how most languages construct structures. To have the members of a structure be is the same order as in memory (C-like), the #ordered
tag can be used.
A :: struct #ordered {
a: u32;
b: u8;
c: f32;
}
To remove all extra memory padding, the #packed
tag can be used.
A :: struct #packed {
a: u32;
b: u8;
c: u16;
d: u8;
}
compile_assert(size_of(A) == 8);
#ordered
and #packed
can not be used to together.
To force a specific alignment to a structure, the #align
tag can be used. The alignment specified must be a power of 2 and in bytes.
A :: struct #align 8 {
a: u8;
}
The#raw_union
tag will cause each field to share the same memory offset, zero, and the size of the largest field. This is equivalent to C's union
. Accessing fields is unsafe if the data is not expected.
Data :: struct #raw_union {
f: f64;
i: i64;
s: string;
b: bool;
c: complex128;
};
d: Data;
d.f = 123;
d.s = "jellied eels";
These are very useful when interfacing with C-library that require C-like unions. They are also useful mathematical objects:
Vector3 :: struct #raw_union {
using xyz: struct {x, y, z: f32};
e: [3]f32;
};
Accessing fields
Structure fields are accessed by using a dot.
Vector2 :: struct{x, y: f32};
main :: proc() {
v := Vector2{4, 9};
v.x = 2;
fmt.println(v);
}
Structure fields can accessed through a pointer. To access the x
field of a pointer to the structure, p^.x
could be written however, Odin allows us to write just p.x
, without the explicit deference. This is to help with refactoring when changing variables from pointer to values, and vice versa.
v := Vector2{4, 9};
p := &v;
p.x = 1.23;
fmt.println(v);