Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is alignof of a char array always 1?

I'm reading a bit about alignment in C++, and I am not sure why the alignment of a class that contains solely a char array member is not the sizeof of the array, but turns out to be always 1. For example

#include <iostream>

struct Foo{char m_[16];}; // shouldn't this have a 16 byte alignment?!

int main()
{
    std::cout << sizeof(Foo) << " " << alignof(Foo);
}

Live on Coliru

in the code above it's clear that the sizeof(Foo) is 16, however its alignment is 1, see the output of the code.

Why is the alignof(Foo) 1 in this case? Note that if I replace char m_[16]; with a fundamental type like int m_;, then alignof(Foo) becomes what I would've expected, i.e. sizeof(int) (on my machine this is 4).

Same happens if I simply declare an array char arr[16];, then alignof(arr) will be 1.

like image 316
vsoftco Avatar asked Mar 01 '17 05:03

vsoftco


1 Answers

Note: data alignment has been explained in details in this article. If you want to know what the term means in general and why it is an important issue read the article.

Aligment is defined in C++ as an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated [6.11.1] Alignment.

Moreover alignments must be non-negative integral powers of 2 [6.11.4] Alignment.

When we calculate the alignment of a struct we have to take into account yet another rule [6.11.5] Alignment:

Alignments have an order from weaker to stronger or stricter alignments. Stricter alignments have larger alignment values. An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.

It's not directly stated but these rules imply that struct alignment has to be at least as strict as the alignment of its most strictly aligned member. It could be bigger but it doesn't have to be and usually isn't.

So when the alignment of the struct from OP's example is decided the alignment of the struct must be no less than alignment of its only member's type char[16]. Then by the 8.3.6 [expr.alignof]:

When alignof is applied to a reference type, the result is the alignment of the referenced type. When alignof is applied to an array type, the result is the alignment of the element type.

alignof(char[16]) equals alignof(char) which will usually be 1 because of [6.11.6] Alignment:

(...) narrow character types shall have the weakest alignment requirement.

In this example:

struct Foo
{
    char c[16];
    double d;
};

double has more strict alignment than char so alignof(Foo) equals alignof(double).

like image 56
mpiatek Avatar answered Oct 12 '22 15:10

mpiatek