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
?
Alignment isn't what you think it is. It's not the number of bytes between locations where two objects of a type can coexist. It's the number of bytes between valid addresses where an object of a type could be allocated.
It doesn't matter that trying to put two instances of Silly
at consecutive aligned addresses would overlap.