module pind.samples.ja.memory.memory_4; 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)は、 * 型のメンバー名の'文字列'コレクションだ。 */ 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); } struct A { byte b; int i; ubyte u; } void main() { printObjectLayout!A(); }