I have written a very simple example which demonstrates the address alignment of a 3-byte struct.
#include <iostream> struct Silly { char a; char b; char c; }; int main() { std::cout << "sizeof(Silly): " << sizeof(Silly) << std::endl; std::cout << "alignof(Silly): " << alignof(Silly) << std::endl; auto p_silly = new Silly[2]; std::cout << "address[0]: " << &p_silly[0] << std::endl; std::cout << "address[1]: " << &p_silly[1] << std::endl; std::cout << "stride: " << &p_silly[1] - &p_silly[0] << std::endl; delete[] p_silly; } Compiling this with g++ -std=c++23, I find the following results:
sizeof(Silly): 3 alignof(Silly): 1 address[0]: 0x63b1ada176c0 address[1]: 0x63b1ada176c3 stride: 1 This output doesn't make any sense to me.
sizeof() = 3 is sensible, since the struct contains 3 bytes of data. There is no padding, since each field is a char, processors can load and store single bytes from any address.
alignof() = 1 doesn't make any sense to me. The alignment is the number of bytes between successive addresses where an object can be allocated. I would expect to see a value of 3 here?
The two addresses show that two struct Silly have been allocated next to each other, with no padding. The address of the second object is 3 bytes further along than the first. This makes sense.
stride initially confused me, but I realized this is the number of elements between the two addresses. Initially I thought it should be the number of bytes between the two addresses.
Why is alignof equal to 1?
alignof(T)<=(1 << std::countr_zero( sizeof(T) )).structis, practically, typically determined by alignment of its largest member. Alignments of astructare determined by the member with maximum alignment (which for astructwith all memberscharis1), and the sum of sizes of all members (in your case,3), usually rounded up to a power of2. Which power of2depends on the target platform (e.g. often different for 16 bit, 32 bit, 64 bit platforms), so a value of3may be rounded up to4,8, or more.