Packing of Struct Fields
Ali Çehreli
acehreli at yahoo.com
Fri Oct 16 20:52:49 UTC 2020
On 10/16/20 1:32 PM, Per Nordlöw wrote:
> Why is `T.sizeof` 12 instead of 8 when `U.sizeof` is 8 in the following
> example?
>
> struct S
> {
> int i;
> bool b;
> }
>
> struct T
> {
> S s;
> char c;
> }
>
> struct U
> {
> int i;
> bool b;
> char c;
> }
>
> ?
I have a function that dumps member layout of structs, which someone may
find useful:
http://ddili.org/ders/d.en/memory.html#ix_memory..offsetof
It prints the following for these types:
=== Memory layout of 'S' (.sizeof: 8, .alignof: 4) ===
0: int i
4: bool b
5: ... 3-byte PADDING
=== Memory layout of 'T' (.sizeof: 12, .alignof: 4) ===
0: S s
8: char c
9: ... 3-byte PADDING
=== Memory layout of 'U' (.sizeof: 8, .alignof: 4) ===
0: int i
4: bool b
5: char c
6: ... 2-byte PADDING
Copied here:
struct S
{
int i;
bool b;
}
struct T
{
S s;
char c;
}
struct U
{
int i;
bool b;
char c;
}
void printObjectLayout(T)()
if (is (T == struct) || is (T == union)) {
import std.stdio;
import std.string;
writefln("=== Memory layout of '%s'" ~
" (.sizeof: %s, .alignof: %s) ===",
T.stringof, T.sizeof, T.alignof);
/* Prints a single line of layout information. */
void printLine(size_t offset, string info) {
writefln("%4s: %s", offset, info);
}
/* Prints padding information if padding is actually
* observed. */
void maybePrintPaddingInfo(size_t expectedOffset,
size_t actualOffset) {
if (expectedOffset < actualOffset) {
/* There is some padding because the actual offset
* is beyond the expected one. */
const paddingSize = actualOffset - expectedOffset;
printLine(expectedOffset,
format("... %s-byte PADDING",
paddingSize));
}
}
/* This is the expected offset of the next member if there
* were no padding bytes before that member. */
size_t noPaddingOffset = 0;
/* Note: __traits(allMembers) is a 'string' collection of
* names of the members of a type. */
foreach (memberName; __traits(allMembers, T)) {
mixin (format("alias member = %s.%s;",
T.stringof, memberName));
const offset = member.offsetof;
maybePrintPaddingInfo(noPaddingOffset, offset);
const typeName = typeof(member).stringof;
printLine(offset,
format("%s %s", typeName, memberName));
noPaddingOffset = offset + member.sizeof;
}
maybePrintPaddingInfo(noPaddingOffset, T.sizeof);
}
void main() {
printObjectLayout!S();
printObjectLayout!T();
printObjectLayout!U();
}
Ali
More information about the Digitalmars-d-learn
mailing list