zig
zig copied to clipboard
Aligned union fields exceed the union size
Zig Version
0.12.0-dev.3428+d8bb139da
Steps to Reproduce and Observed Behavior
const std = @import("std");
pub fn main() !void {
const S = union(enum) {
a: i16 align(1),
b: f64 align(1),
};
var a: S = .{ .b = 5000 };
std.log.debug("Size: {}", .{@sizeOf(S)});
std.log.debug("Alignment: {}", .{@alignOf(S)});
std.log.debug("S.b offset: {x}", .{@intFromPtr(&a.b) - @intFromPtr(&a)});
}
Output:
debug: Size: 9
debug: Alignment: 1
debug: S.b offset: 8
This means that S.b will exceed the union size. It can be observed in the following example:
const std = @import("std");
pub fn main() !void {
const S = union(enum) {
a: i16 align(1),
b: f64 align(1),
};
var a: S = .{ .b = 5000 };
a.b = 5001;
const b: [3]S = .{ a, a, a };
std.log.debug("{any}", .{b});
}
Output:
debug: { main.main.S{ .b = 0e0 }, main.main.S{ .b = -3.3428705905156227e196 }, main.main.S{ .a = } }
However it works fine with constant a:
const std = @import("std");
pub fn main() !void {
const S = union(enum) {
a: i16 align(1),
b: f64 align(1),
};
const a: S = .{ .b = 5000 };
const b: [3]S = .{ a, a, a };
std.log.debug("{any}", .{b});
}
Output:
debug: { main.main.S{ .b = 5e3 }, main.main.S{ .b = 5e3 }, main.main.S{ .b = 5e3 } }
Expected Behavior
Aligned union fields must not exceed the union size.