Padding and alignment

S

Spoon

Hello everyone,

I had expected my C++ compiler to add padding within classes and structs
to align fields to their "natural" boundary. This seems not to be true.

$ cat align.cxx
#include <cstdio>
struct foo
{
virtual void f() const { }
long long x;
};
int main()
{
foo bar;
printf("%p %p\n", (void *)&bar, (void *)&bar.x);
return 0;
}

$ ./a.out
0xbfd9da00 0xbfd9da04

On my platform (x86 Linux g++) long long is 64-bits wide.
(I suppose the first 4 bytes store the v-pointer.)
Why didn't the compiler add padding to align x to a 64-bit boundary?

Regards.
 
R

red floyd

Spoon said:
Hello everyone,

I had expected my C++ compiler to add padding within classes and structs
to align fields to their "natural" boundary. This seems not to be true.

$ cat align.cxx
#include <cstdio>
struct foo
{
virtual void f() const { }
long long x;
};
int main()
{
foo bar;
printf("%p %p\n", (void *)&bar, (void *)&bar.x);
return 0;
}

$ ./a.out
0xbfd9da00 0xbfd9da04

On my platform (x86 Linux g++) long long is 64-bits wide.
(I suppose the first 4 bytes store the v-pointer.)
Why didn't the compiler add padding to align x to a 64-bit boundary?

Regards.

That's an implementation specific issue, having nothing to do with the
language itself, and is therefore OT in comp.lang.c++. May I suggest
asking in gnu.g++.help?

Followups set to gnu.g++.help
 
R

Rolf Magnus

Spoon said:
Hello everyone,

I had expected my C++ compiler to add padding within classes and structs
to align fields to their "natural" boundary. This seems not to be true.

$ cat align.cxx
#include <cstdio>
struct foo
{
virtual void f() const { }
long long x;
};
int main()
{
foo bar;
printf("%p %p\n", (void *)&bar, (void *)&bar.x);
return 0;
}

$ ./a.out
0xbfd9da00 0xbfd9da04

On my platform (x86 Linux g++) long long is 64-bits wide.
(I suppose the first 4 bytes store the v-pointer.)
Why didn't the compiler add padding to align x to a 64-bit boundary?

What makes you think it should? Generally, C++ doesn't dictate any
alingment. On some 32 bit systems, the maximum needed alignment is 32 bits,
so why waste memory by using an alignment greater than needed if you don't
gain anything from it?
I'm writing C++ code for an 8 bit platform which doesn't have any specific
alignment reqirements, so every type is byte aligned.
 
G

Grizlyk

Spoon said:
struct foo
{
virtual void f() const { }
long long x;
};

int main()
{
foo bar;
printf("%p %p\n", (void *)&bar, (void *)&bar.x);
return 0;
}

$ ./a.out
0xbfd9da00 0xbfd9da04

On my platform (x86 Linux g++) long long is 64-bits wide.
(I suppose the first 4 bytes store the v-pointer.)

Wait.
1. What is v-pointer?
2. Why member foo::x has nonzero offset from foo memory start?
 
P

Pan

Rolf said:
I'm writing C++ code for an 8 bit platform which doesn't have any specific
alignment reqirements, so every type is byte aligned.

BTW, x86 architecture don't have specific alignment requirements, too.
 
R

red floyd

Grizlyk wrote:


DISCLAIMER: THIS IS OFF-TOPIC, AS THE STANDARD DOES NOT DISCUSS
VPTR/VTBL MECHANISMS.

However, as most, if not all, implementations use it....
1. What is v-pointer?
Pointer to the virtual function table for the class (not required by the
standard, but most known implementations do this).
2. Why member foo::x has nonzero offset from foo memory start?
For the vptr. Each object with virtual functions in g++ -- again, not
required by the STandard -- has a pointer to a per-class table which
contains the addresses of the virtual functions for that class. It
generally lives at the start of the class, hence the rationale behind
foo::x not having 0 offset.
 
G

Grizlyk

red said:
However, as most, if not all, implementations use it....

Pointer to the virtual function table for the class (not required by the
standard, but most known implementations do this).

For the vptr. Each object with virtual functions in g++ -- again, not
required by the STandard -- has a pointer to a per-class table which
contains the addresses of the virtual functions for that class. It
generally lives at the start of the class, hence the rationale behind
foo::x not having 0 offset.

For the first, there are no virtual functions declared in the class, so no
vtable exist.

For the second, I have read many times, that C++ classes have designed to be
similar to C structures, so C++ data is very like to C-structure, but
C-structure has zero offset for first member and has well-defined theorder
of the members.

I do not think, that the equality is important or needed, but to make it,
for C++ extra hidden data, as pointer to vtable and so on, because of sizeof
of all visible data is known at compile time, all extra hidden data can be
placed _after_ all. For inherited classes new data can be placed after all
data of base class. But may be pointer to vtable befor all data is more
regular than pointer to vtable mixed with data.
 
R

Robert Mabee

Rolf said:
Generally, C++ doesn't dictate any
alingment. On some 32 bit systems, the maximum needed alignment is 32 bits,
so why waste memory by using an alignment greater than needed if you don't
gain anything from it?
I'm writing C++ code for an 8 bit platform which doesn't have any specific
alignment reqirements, so every type is byte aligned.

It's often recommended to align primitive types same as their size (if
not silly like 80 bit floating point). This comes from sad experience
with CPUs that evolve to wider busses, making the former two-word type
either inefficient or fatal to access on the "wrong" alignment. An
otherwise compatible CPU requires painful coding to use such things as
structures saved on disk.

Sounds like a short-sighted mistake in adding 64 bit types to the x86
compiler. Too late to fix it. It is now up to the user to craft any
structure that might be permanent or exported so that it has explicit
padding to this "natural" alignment. Probably it makes no sense to
export an object with a vtable pointer in a raw form so its effect on
alignment can be ignored.
 
R

red floyd

Grizlyk said:
red floyd wrote:


For the first, there are no virtual functions declared in the class, so no
vtable exist.

Really? From the OP:
> struct foo
> {
> virtual void f() const { }
> long long x;
> };

For the second, I have read many times, that C++ classes have designed to be
similar to C structures, so C++ data is very like to C-structure, but
C-structure has zero offset for first member and has well-defined theorder
of the members.

Only for POD.
 
R

red floyd

Grizlyk said:
For the first, there are no virtual functions declared in the class, so no
vtable exist.

Really? From the OP:
> struct foo
> {
> virtual void f() const { }
> long long x;
> };

For the second, I have read many times, that C++ classes have designed to be
similar to C structures, so C++ data is very like to C-structure, but
C-structure has zero offset for first member and has well-defined theorder
of the members.

Only for POD.
 
R

Rolf Magnus

Pan said:
BTW, x86 architecture don't have specific alignment requirements, too.

It depends. Some instructions are slower when used on misaligned data, some
won't work at all.
 
R

Rolf Magnus

Grizlyk said:
For the second, I have read many times, that C++ classes have designed to
be similar to C structures, so C++ data is very like to C-structure, but
C-structure has zero offset for first member and has well-defined theorder
of the members.

POD ("plain old data") classes in C++ have that, too. Basically, a
simplified definition of "POD" is "similar to what C would do". Adding a
virtual member function makes your class non-POD.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top