nested unions and structs

Regan Heath regan at netwin.co.nz
Thu Apr 27 14:36:26 PDT 2006


On Thu, 27 Apr 2006 18:28:05 +0000 (UTC), Alberto Simon  
<Alberto_member at pathlink.com> wrote:
> It looks like I didn't explain myself. I expect that when I declare a  
> DWord
> union and try to access its fields, Data should have the same address  
> LowerWord
> has and the same address Low on LowerWord has, but that does not happen,  
> Data
> instead is 4 bytes after LowerWord, and that ticks me, since all fields  
> of an
> union should start at the same address.

For me, LowerWord is 2 bytes _after_ Data and it's there because  
HigherWord aligns with Data and LowerWord comes _after_ HigherWord in the  
anonymous struct in DWord. In other words it's all working correctly as  
far as I can see.

If you want LowerWord and Data to align you have to reverse the order of  
LowerWord and HigherWord, eg.

public union DWord {
	public uint Data;	
	struct
	{		
		public Word LowerWord;
		public Word HigherWord;
	};
}

Here is a semi-graphical representation of the current memory locations.

public union Word {
	struct {
		public ubyte Low;
		public ubyte High;
	}
	public ushort Data;
}

public union DWord {
	public uint Data;	
	struct
	{
		public Word HigherWord;
		public Word LowerWord;
	};
}

import std.stdio;

void main()
{
	Word w;
	DWord d;
	
	writefln("public union Word { ",&w);
	writefln("\tstruct {");
	writefln("\t\tpublic ubyte Low; ",&w.Low);
	writefln("\t\tpublic ubyte High; ",&w.High);
	writefln("\t}");
	writefln("\tpublic ushort Data; ",&w.Data);	
	writefln("}");
	
	writefln("public union DWord { ",&d);
	writefln("\tpublic uint Data; ",&d.Data);
	writefln("\tstruct {");
	writefln("\t\tpublic Word HigherWord { ",&d.HigherWord);
	writefln("\t\t\tpublic ushort Data; ",&d.HigherWord.Data);
	writefln("\t\t\tstruct {");
	writefln("\t\t\t\tpublic ubyte Low; ",&d.HigherWord.Low);
	writefln("\t\t\t\tpublic ubyte High; ",&d.HigherWord.High);
	writefln("\t\t\t}");
	writefln("\t\t}");
	writefln("\t\tpublic Word LowerWord { ",&d.LowerWord);
	writefln("\t\t\tpublic ushort Data; ",&d.LowerWord.Data);
	writefln("\t\t\tstruct {");
	writefln("\t\t\t\tpublic ubyte Low; ",&d.LowerWord.Low);
	writefln("\t\t\t\tpublic ubyte High; ",&d.LowerWord.High);
	writefln("\t\t\t}");
	writefln("\t\t}");
	writefln("\t}");
	writefln("}");
}

Results:

public union Word { 12FF30
         struct {
                 public ubyte Low; 12FF30
                 public ubyte High; 12FF31
         }
         public ushort Data; 12FF30
}
public union DWord { 12FF34
         public uint Data; 12FF34
         struct {
                 public Word HigherWord { 12FF34
                         public ushort Data; 12FF34
                         struct {
                                 public ubyte Low; 12FF34
                                 public ubyte High; 12FF35
                         }
                 }
                 public Word LowerWord { 12FF36
                         public ushort Data; 12FF36
                         struct {
                                 public ubyte Low; 12FF36
                                 public ubyte High; 12FF37
                         }
                 }
         }
}

Regan



More information about the Digitalmars-d mailing list