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?

3
  • I would expect to see a value of 3 here? Such value may not exist. Alignments are always powers of 2: 1, 2, 4... The shown struct has a layout of char[3] that has the alignment 1 defined by char. Commented Feb 8 at 17:45
  • Normally alignof(T)<=(1 << std::countr_zero( sizeof(T) )). Commented Feb 8 at 18:26
  • Alignment of a standard-layout (eg POD) struct is, practically, typically determined by alignment of its largest member. Alignments of a struct are determined by the member with maximum alignment (which for a struct with all members char is 1), and the sum of sizes of all members (in your case, 3), usually rounded up to a power of 2. Which power of 2 depends on the target platform (e.g. often different for 16 bit, 32 bit, 64 bit platforms), so a value of 3 may be rounded up to 4, 8, or more. Commented Feb 9 at 1:06

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.