1

This question is related to How to ensure a member is 4-byte aligned?

Example:

struct Aligned
{
    char c;
    __attribute__((__aligned__(4))) int32_t member;
}

struct Test
{
    char    c;
    Aligned s;//is s.member 4 bytes aligned?
}


void f1()
{
    char    c1;
    Aligned s;//is s.member 4 bytes aligned?
    char    c2;
}

void f2()
{
    Aligned* s = new Aligned();//is s.member 4 bytes aligned?
}

Can you please explain if "member" is 4 bytes aligned in all cases, and if yes how this works?

Edit: I forgot the case where Aligned is derived from other struct:

struct Aligned : public SomeVariableSizeStruct
{
    char c;
    __attribute__((__aligned__(4))) int32_t member;
}

Second Edit: My questions is: is always first member of a structure 4 bytes aligned? Because in all cases presented here the first variable address might not be 4 bytes aligned and the 3 bytes padding doesn't guarantee that "member" is 4 bytes aligned

Community
  • 1
  • 1
Mircea Ispas
  • 20,260
  • 32
  • 123
  • 211
  • You don't need to force alignment. Struct padding will handle it all for you. So yes, it will be aligned in all the examples you have provided. – Mysticial Aug 16 '12 at 08:33

4 Answers4

5

Yes, it works. The compiler is required to make it work.

Every type has an alignment which the compiler has to respect. You've specified that one particular object should use 4-byte alignment, but every other object, a char, an int, a std::string and anything else also have their own alignment requirements.

So the compiler is used to having to cope with this.

To determine the alignment required for Aligned, the compiler basically goes through all its members (as well as its base class(es) to find the one that requires the strictest alignment. This then becomes the alignment required for Aligned as well.

The most aligned member in this case is member, which requires 4-byte alignment. So Aligned requires 4-byte alignment.

And yes, this is guaranteed whether you create an Aligned on the stack as a function local variable, or as another class member, or on the heap with new.

jalf
  • 243,077
  • 51
  • 345
  • 550
4

How does it works?

When you define a struct, you define how memory will be used when handled as this struct. This means that when defining your struct as follows

struct Aligned
{
    char c;
    __attribute__((__aligned__(4))) int32_t member;
}

The compiler defines how to handle the memory corresponding to this struct Aligned. For instance, the compiler will use the memory* with the following layout:

bytes: |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
usage: |  c  |  X  |  X  |  X  |        member         |

X means these bytes are not used. This is called padding.

*: Note this is true for x86 architectures, and may differ on other. But the fact of not using some bytes is the same.

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
1

Can you please explain if "member" is 4 bytes aligned in all cases, and if yes how this works?

Yes, it is. The exception is if you tell the compiler to pack your structure.

How it works? The compiler invisibly aligns everything. It adds padding/space between members. It's a requirement for ABIs and for generating the assembly. Of course, the programmer is still capable of using data which is not naturally aligned.

As an optimization, the compiler may reorder your members -- in some circumstances: Can a C++ compiler re-order elements in a struct

Community
  • 1
  • 1
justin
  • 104,054
  • 14
  • 179
  • 226
  • 2
    I'm not the downvoter, but I don't think that the compiler is allowed to re-order members. That would break binary compatibility with other modules/libraries that don't reorder them. – Mysticial Aug 16 '12 at 08:45
  • Yeah, reordering is not allowed – jalf Aug 16 '12 at 08:49
  • @jalf this seems to contradict what you said here about reordering: http://stackoverflow.com/questions/916600/can-a-c-compiler-re-order-elements-in-a-struct – justin Aug 16 '12 at 08:58
  • @Mysticial thanks for the explanation (+1). however, i dragged out a reference (above). am i just too sleepy to see what's wrong here? – justin Aug 16 '12 at 09:01
  • 2
    Ok, reordering is not allowed, *except* across access specifiers. I was trying to keep it simple, and in the cases shown in the OP's code, reordering must not be done. :) – jalf Aug 16 '12 at 09:02
  • @jalf alrighty. i'll add the link to the answer so the condition is clear. thanks. – justin Aug 16 '12 at 09:04
  • 1
    By the way, I actually tested that a few days ago: turns out neither Clang, GCC or MSVC actually make use of this provision. They never seem to reorder members at all, even when it's allowed, and where it could result in smaller object sizes – jalf Aug 16 '12 at 09:06
  • @jalf Unlike padding, I figure it's hard to ensure that it's done consistently across all compilers. So they don't bother with it. That's probably why reordering is disallowed in the first place. – Mysticial Aug 16 '12 at 09:24
  • @jalf i was curious; i found a few that did use it. i'm not sure if they still do… http://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg184579.html – justin Aug 16 '12 at 09:29
0

It works, because the compiler has to make it work. The compiler will internally have a description of type Aligned that includes such properties as its name and sizeof, but also alignment restrictions.

MSalters
  • 173,980
  • 10
  • 155
  • 350