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

Determine alignment offset of base class

37 views
Skip to first unread message

Marcel Mueller

unread,
Feb 27, 2021, 1:00:14 AM2/27/21
to
Given a type T has a memory alignment alignof(T) and a base class B.
B will in general not have the same alignment as T. But B cannot appear
at arbitrary locations, only every alignof(T).

For some low level programming I need the alignment offset of B within a
given type T. Something like
offsetof(T, B) % alignof(T)

Of course the old offsetof macro will not work this way. But is there a
way to extract this offset, preferably as constexpr?

I know that there are limitations when B is a virtual base of T. The
offset is no longer defined in this case.


Marcel

James Kuyper

unread,
Feb 27, 2021, 9:22:14 AM2/27/21
to
"Use of the offsetof macro with a type other than a standard-layout
class (11.2) is conditionally-supported. ... The result of applying the
offsetof macro to a static data member or a function member is
undefined." (17.2.4p1)

As a general rule, if there is in fact a constant offset from the
beginning of a given class instance to a given member of that object,
the behavior of offsetof() will be well-defined, and the implementation
will support the use of offsetof() for obtaining that offset. To put it
the other way around, if use of offsetof() has undefined behavior or is
not supported, then the distance between those two things might not be
constant. Therefore, if you can't use offsetof(), it's unlikely that
there will be any workaround.

Chris M. Thomasson

unread,
Feb 28, 2021, 2:39:20 PM2/28/21
to
I have no idea if this will work for you, or if its even standard with
regard to the use of alignas for virtual base classes.

__________________________________
#include <iostream>
#include <cstdint>
#include <cassert>


#define ALIGN 128


struct alignas(ALIGN) base
{
int a;
char b;
long c;

base()
{
std::cout << "base::base() " << this << "\n";
}

virtual ~base()
{
std::cout << "base::~base() " << this << "\n";
}

std::uintptr_t base_this() { return (std::uintptr_t)this; }
};


struct alignas(ALIGN) foo : virtual public base
{
int d;

foo()
{
std::cout << "foo::foo() " << this << "\n";

std::uintptr_t dif = base_this() - (uintptr_t)this;

std::cout << "dif = " << dif << "\n";

assert(dif == ALIGN);
}

~foo()
{
std::cout << "foo::~foo() " << this << "\n";
}
};

int main()
{
{
foo f;
}

return 0;
}

__________________________________


I am getting:

base::base() 010FF680
foo::foo() 010FF600
dif = 128
foo::~foo() 010FF600
base::~base() 010FF680


dif should always equal the alignment. What do you get on your end?

Chris M. Thomasson

unread,
Feb 28, 2021, 3:05:15 PM2/28/21
to
On 2/28/2021 11:39 AM, Chris M. Thomasson wrote:
> On 2/26/2021 10:00 PM, Marcel Mueller wrote:
>> Given a type T has a memory alignment alignof(T) and a base class B.
>> B will in general not have the same alignment as T. But B cannot
>> appear at arbitrary locations, only every alignof(T).
>>
>> For some low level programming I need the alignment offset of B within
>> a given type T. Something like
>>    offsetof(T, B) % alignof(T)
>>
>> Of course the old offsetof macro will not work this way. But is there
>> a way to extract this offset, preferably as constexpr?
>>
>> I know that there are limitations when B is a virtual base of T. The
>> offset is no longer defined in this case.
>
> I have no idea if this will work for you, or if its even standard with
> regard to the use of alignas for virtual base classes.
>
> __________________________________
> [....]
> I am getting:
>
> base::base() 010FF680
> foo::foo() 010FF600
> dif = 128
> foo::~foo() 010FF600
> base::~base() 010FF680
>
>
> dif should always equal the alignment. What do you get on your end?

My "rational" is that if we over align the the base class and the
derived class on a common alignment, then they should both share that
alignment.

Marcel Mueller

unread,
Mar 1, 2021, 2:16:00 AM3/1/21
to
Am 28.02.21 um 20:39 schrieb Chris M. Thomasson:
> struct alignas(ALIGN) base
> struct alignas(ALIGN) foo : virtual public base

It is trivial when the base class has a greater or same alignment. In
this case there is no offset.

But when base is used in different subclasses with different alignments
it makes no longer sense. In this case base may appear e.g. at
0x...108, 0x...308, 0x...308 etc.

Now the algorithm has to deal with the 08 offset in the alignment.


Marcel

Bonita Montero

unread,
Mar 1, 2021, 1:39:48 PM3/1/21
to
> struct alignas(ALIGN) foo : virtual public base

Not necessary. The derived class inherits the alignment and if the
specified alignment of the derived class is less, it is ignored.

Chris M. Thomasson

unread,
Mar 1, 2021, 7:37:17 PM3/1/21
to
Ahhh... Okay, thanks Bonita. :^)

Chris M. Thomasson

unread,
Mar 1, 2021, 10:18:00 PM3/1/21
to
I don't think there is a standard way to do it without forcing alignment
with alignas.

0 new messages