Consider a u24. On most systems, this will align to 4, and thus require 4 bytes to store.
Is the data for the u24 in the lowest memory addresses of the 4 bytes (bytes 0,1,2) , the highest memory addresses (bytes 1,2,3), or does this depend on the endian-ness of the host?
I’m surprised to see the unused bits set to undefined. I assume that’s some sort of safety measure, at the cost of having to mask it off in Debug and (maybe?) Safe modes?
I guess the main reason I ask it about packed structs.
As we know, packed structs have a backing integer. I wonder where the padding due to alignment is? Its definitely not between the fields, so I am wondering which side of the fields its on?
To be perhaps excessively pedantic, the padding is always high. It pays to be careful about the distinction between least and most significant aka low and high, on the one hand, and first and last on the other. The latter could mean the same thing, or could be something which depends on the endianness of the target.
test "where is the data in a u24" {
var memory: [4]u8 align(4) = .{ 0x00, 0x11, 0x22, 0xaa };
const number: *u24 = @alignCast(@ptrCast(&memory));
switch (@import("builtin").cpu.arch.endian()) {
.little => {
try std.testing.expectEqual(@as(u24, 0x221100), number.*);
std.debug.print("ran little endian\n", .{});
},
.big => {
try std.testing.expectEqual(@as(u24, 0x001122), number.*);
std.debug.print("ran big endian\n", .{});
},
}
}
ran using standard build script and zig build test -Dtarget=powerpc64-linux using host x86_64 and QEMU.
jeff@jeff-debian:~/repos/gatorcat$ zig build test -Dtarget=powerpc64-linux
test
└─ run test stderr
ran big endian
jeff@jeff-debian:~/repos/gatorcat$ zig build test
test
└─ run test stderr
ran little endian
which means the data is in the lowest memory addresses.
Does this contradict you @mnemnion (data is always in “high” bits) or am I testing incorrectly?