I'd like to understand more about alignment. Why does the Microsoft compiler (Visual Studio 2012 Express) complain about the alignment for the following snippet of code?
__declspec(align(16)) class Foo
{
public:
virtual ~Foo() {}
virtual void bar() = 0;
};
This is the warning the compiler presents to me:
warning C4324: 'Foo' : structure was padded due to __declspec(align())
It does not even matter whether or not the class has any virtual methods. Even for an empty class the compiler complains with the same warning message. How is an empty class aligned? How does the compiler pad this class?
A warning does not necessarily mean you've done something wrong, but tells you that you might not have intended this behaviour. Note that a compiler is allowed to warn about anything the developers considered worth warning about. In principle, you could also be warned about compiling on Friday the 13th.
In this specific case the assumption probably is that when you specify alignment, you don't want to make the class bigger. Therefore if the class gets bigger due to the alignment requirement you gave, it's not unlikely that you made a mistake.
Of course that leaves the question why the alignment requirement makes the class bigger. Now we are back in standards land (although the __declspec
itself is a Microsoft extension and not standard). The C++ standard requires that in arrays, the objects follow each other without any space in between. Therefore if your objects must be aligned to 16-byte boundaries, the object must have a size which is a multiple of 16. If the size of the members (both explicit and implicit) doesn't give the necessary size, the compiler has to add unused bytes to the object. These bytes are called padding. Note that this padding is present even in objects which are not members of arrays.
Now your class only contains an implicit virtual pointer (because it contains virtual functions) which, depending on the architecture, probably is either 4 or 8 bytes large. Since you've requested 16 byte alignment, the compiler has to add 12 or 8 bytes of padding to get the size to a multiple of 16, which it would not have had to add without that manual alignment specification. And this is what the compiler warns about.