module pind.samples.ja.memory.memory_6; import std.stdio; 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); /* レイアウト情報の1行を表示する。 */ void printLine(size_t offset, string info) { writefln("%4s: %s", offset, info); } /* パディングが実際に確認された場合、 * パディング情報を表示する。 */ void maybePrintPaddingInfo(size_t expectedOffset, size_t actualOffset) { if (expectedOffset < actualOffset) { /* 実際のオフセットが * 予想オフセットを超えているため、パディングがある。 */ const paddingSize = actualOffset - expectedOffset; printLine(expectedOffset, format("... %s-byte PADDING", paddingSize)); } } /* そのメンバーの前にパディングバイトがない場合、 * 次のメンバーの予想オフセット。 */ size_t noPaddingOffset = 0; /* 注釈: __traits(allMembers)は、 * 型のメンバー名の'string'コレクションだ。 */ 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); } align (2) // 'S'オブジェクトのアライメント struct S { byte b; align (1) int i; // メンバー'i'のアライメント ubyte u; } void main() { printObjectLayout!S(); }