Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

_Alignof structs

55 views
Skip to first unread message

Thiago Adams

unread,
Nov 10, 2022, 1:50:34 PM11/10/22
to
What is the idea behind alignof structs?

I tried this code in gcc

struct X {
char i;
char s;
};
_Static_assert(_Alignof(struct X) == 1, "");

int main(){}

The result seems to be the alignof the first element of struct.
Changing i for int or double changes the ouput.
I was expecting the max alignment before checking it.

Keith Thompson

unread,
Nov 10, 2022, 2:57:12 PM11/10/22
to
I'm not sure why you'd expect the max alignment.

gcc could have required 2-byte alignment for struct X (or even a 4-byte
alignment with padding bytes after the last member), but it allows a
struct X object to be at any byte boundary.

The alignment for a structure is at least the maximum alignment of any
of its members. If all the members are single bytes, the structure
alignment can be 1 or it can be more strict, at the whim of the compiler
(probably guided by some ABI). And if a struct X is allocated at an odd
address, the compiler does whatever is needed to make it work.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

Thiago Adams

unread,
Nov 11, 2022, 5:57:50 AM11/11/22
to
On Thursday, November 10, 2022 at 4:57:12 PM UTC-3, Keith Thompson wrote:
> Thiago Adams <thiago...@gmail.com> writes:
> > What is the idea behind alignof structs?
> >
> > I tried this code in gcc
> >
> > struct X {
> > char i;
> > char s;
> > };
> > _Static_assert(_Alignof(struct X) == 1, "");
> >
> > int main(){}
> >
> > The result seems to be the alignof the first element of struct.
> > Changing i for int or double changes the ouput.
> > I was expecting the max alignment before checking it.
> I'm not sure why you'd expect the max alignment.

I was expecting a fixed the max alignment to be possible to
have a fixed reference for padding. The way I think it works (with padding)
is to have each member positioned on it own alignment.
I am trying to see now (thinking in some samples), if placing struct at the
max member aligment will result in each member on its own aligment (considering padding)


Keith Thompson

unread,
Nov 11, 2022, 6:08:03 PM11/11/22
to
I don't understand.

For this structure, no padding is necessary, and the members can be
accessed correctly regardless of the alignment of the structure. The
maximum alignment of any member is 1 (char is 1 byte, and char arrays
wouldn't work if char required a stricter alignment), which means that
the alignment of the struct has to be *at least* 1.

What exactly do you mean by "max alignment", and why are you expecting
it to be something other than 1?

I wouldn't have been surprised of the alignment of the structure had
been 2, but gcc chooses to give it a 1-byte alignment, likely because
the relevant ABI requires it.

Thiago Adams

unread,
Nov 11, 2022, 9:08:26 PM11/11/22
to
Same returned by malloc.


> I wouldn't have been surprised of the alignment of the structure had
> been 2, but gcc chooses to give it a 1-byte alignment, likely because
> the relevant ABI requires it.
> --



I think it is more clear to me now. I played with compiler explorer C++ mode
msvc compiler and /d1reportSingleClassLayoutCLASSNAME

for instance
struct X{
char s;
double c;
char s2;
}

https://godbolt.org/z/T9T8538Kh

prints

class X size(24):
+---
0 | s
| <alignment member> (size=7)
8 | c
16 | s2
| <alignment member> (size=7)
+---


The bigger element defines the struct alignment.


struct X{
char s;
struct Y {char s2; int i;} d;
double c;
char s2;
};

class X size(32):
+---
0 | s
| <alignment member> (size=3)
4 | Y d
| <alignment member> (size=4)
16 | c
24 | s2
| <alignment member> (size=7)
+---


struct X{
char s;
struct Y {char s2; double i;} d;
double c;

char s2;
}
;
prints

class X size(40):
+---
0 | s
| <alignment member> (size=7)
8 | Y d
24 | c
32 | s2
| <alignment member> (size=7)
+---


struct X{
char c;
short s;
}
;
class X size(4):
+---
0 | c
| <alignment member> (size=1)
2 | s
+---
so...if the alignment of this last struct is 2..it can be placed in address divisible by
2 or 4 or 8 .but no divisible by 1.

for instance , like 13, because in this case 's' would be at 13+2=15
that is not aligned for short.


changing 's' from short to int the struct can be placed in address divisible
by 4 or 8. so address 14 for instance is not allowed.

Richard Damon

unread,
Nov 11, 2022, 10:09:32 PM11/11/22
to
The key point is that the alignment of a structure needs to be AT LEAST
as strict as the alignment of the strictest member, but might need to be
stricter.

In fact, for some machines it might need to be, because another rule is
that the representation of a pointer to a sturcture must be known
without knowing the definition of the structure, so if your machine uses
different representation pointers (like a machine that natively
addresses bigger than byte chunks) the implementation needs to pick one
for all structure pointers, and normally chooses the one which is more
natural, even if it has a stricter alignment requirement then a more
general format.

Sometimes, even if this isn't an issue, sometimes the compiler will
still use a stricter alignment if it makes some operation easier.

For instance, for the above structure, it might use an alignment of 2,
so that an assignment of one object of this type to another could use a
two byte load and store instruction to be quicker and shorter instead of
two seperate 1 byte operations.

Andrey Tarasevich

unread,
Nov 11, 2022, 10:22:53 PM11/11/22
to
On 11/10/2022 10:50 AM, Thiago Adams wrote:
> What is the idea behind alignof structs?
>
> I tried this code in gcc
>
> struct X {
> char i;
> char s;
> };
> _Static_assert(_Alignof(struct X) == 1, "");
>
> int main(){}
>
> The result seems to be the alignof the first element of struct.
> Changing i for int or double changes the ouput.

That's bizarre. A natural thing to expect would be maximum _Alignof
among all members. How you managed to get _Alignof of the _first_
element specifically is not clear to me. I just tried it in gcc and it
worked as expected: maximum _Alignof among all members.

> I was expecting the max alignment before checking it.

What do you mean by "max alignment"? `_Alignof(max_align_t)` or what I
describe above?

--
Best regards,
Andrey

Thiago Adams

unread,
Nov 12, 2022, 5:54:07 AM11/12/22
to
On Saturday, November 12, 2022 at 12:22:53 AM UTC-3, Andrey Tarasevich wrote:
> On 11/10/2022 10:50 AM, Thiago Adams wrote:
> > What is the idea behind alignof structs?
> >
> > I tried this code in gcc
> >
> > struct X {
> > char i;
> > char s;
> > };
> > _Static_assert(_Alignof(struct X) == 1, "");
> >
> > int main(){}
> >
> > The result seems to be the alignof the first element of struct.
> > Changing i for int or double changes the ouput.
> That's bizarre. A natural thing to expect would be maximum _Alignof
> among all members. How you managed to get _Alignof of the _first_
> element specifically is not clear to me. I just tried it in gcc and it
> worked as expected: maximum _Alignof among all members.

>A natural thing to expect would be maximum _Alignof
> among all members
I didn't know that. That was basically my question. So I tried and
by coincidence I put the biggest align on the first element giving me
the wrong interpretation how it works.


> > I was expecting the max alignment before checking it.
> What do you mean by "max alignment"? `_Alignof(max_align_t)` or what I
> describe above?

Yes. the same aligment returned by malloc.

I was trying to understand how different align for structs
would result in the member by member correct aligment (considering padding)


(Sometimes I ask questions that may have the answer somewhere "google it",
but I feel posting here will bring more details and maybe generate more insights)





Po Lu

unread,
Nov 13, 2022, 9:28:57 PM11/13/22
to
Thiago Adams <thiago...@gmail.com> writes:

> Yes. the same aligment returned by malloc.

Then you have to define a union of every built-in type, and take the
alignment of that union.

malloc does not know what type it is allocating memory for, so it
returns memory suitably aligned for *all* built-in types.

Ben Bacarisse

unread,
Nov 13, 2022, 9:45:01 PM11/13/22
to
Po Lu <luan...@yahoo.com> writes:

> Thiago Adams <thiago...@gmail.com> writes:
>
>> Yes. the same aligment returned by malloc.
>
> Then you have to define a union of every built-in type, and take the
> alignment of that union.

Since C11, you can use max_align_t.

--
Ben.

Chris M. Thomasson

unread,
Nov 13, 2022, 9:45:12 PM11/13/22
to
Ding!
0 new messages