c++c++23

Why does this 3-byte struct have an `alignof` value of 1?


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?


Solution

  • 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.