www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - struct.sizeof is wrong when the struct contains a union

reply Geoff Hickey <Geoff_member pathlink.com> writes:
Using dmd v.108 on WinXP, structures that contain named unions don't have the
correct size. In the example below, the size of the structure type "test" is
reported as 1, not 4 as it should be; and the size of the union "junk" inside it
is 4, as expected. Declaring an instance of the structure and taking the size of
it gives the same result.

If the union is made anonymous, the problem disappears.


/*
* Example of structure size error:
*/
import std.stdio;

struct test
{
union junk
{
uint a;
uint b;
}
}

int main()
{
writefln( "Struct size: %s", test.sizeof );
writefln( "Union size: %s", test.junk.sizeof );
assert( test.sizeof >= test.junk.sizeof );
return 0;
}
Dec 02 2004
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 2 Dec 2004 22:01:10 +0000 (UTC), Geoff Hickey  
<Geoff_member pathlink.com> wrote:
 import std.stdio;
 struct test
 {
 union junk
 {
 uint a;
 uint b;
 }
 }
 int main()
 {
 writefln( "Struct size: %s", test.sizeof );
 writefln( "Union size: %s", test.junk.sizeof );
 assert( test.sizeof >= test.junk.sizeof );
 return 0;
 }

Actually, you're not declaring an instance of your union, only the definition, instead try: import std.stdio; struct test { union junk { uint a; uint b; } junk a; } int main() { writefln( "Struct size: %s", test.sizeof ); writefln( "Union size: %s", test.junk.sizeof ); assert( test.sizeof >= test.junk.sizeof ); return 0; } Note: When you write: union junk { uint a; uint b; } you are not declaring an instance of a union, but instead the definition of one, therefore in order to actually put one into your struct you have to declare an instance of one, thus the line: junk a; Anonymous unions are allowed and of course declare an instance instead of a definition. This can definately be a little confusing at first as it's not identical to C/C++. I think this should go into the FAQ (if it's not already) Regan
Dec 02 2004
next sibling parent reply Geoff Hickey <Geoff_member pathlink.com> writes:
In article <opsieivo1m23k2f5 ally>, Regan Heath says...
Note: When you write:

union junk {
   uint a;
   uint b;
}

you are not declaring an instance of a union, but instead the definition  
of one, therefore in order to actually put one into your struct you have  
to declare an instance of one, thus the line:

junk a;


Anonymous unions are allowed and of course declare an instance instead of  
a definition.

This can definately be a little confusing at first as it's not identical  
to C/C++. I think this should go into the FAQ (if it's not already)

Regan

Ah. Gotcha. That being the case, shouldn't the compiler complain when do this?: struct test { union junk { uint a; uint b; } } int main() { test tv; tv.junk.a = 1; } But it doesn't; this program compiles and runs. - Geoff Hickey
Dec 02 2004
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 2 Dec 2004 23:11:21 +0000 (UTC), Geoff Hickey  
<Geoff_member pathlink.com> wrote:
 In article <opsieivo1m23k2f5 ally>, Regan Heath says...
 Note: When you write:

 union junk {
   uint a;
   uint b;
 }

 you are not declaring an instance of a union, but instead the definition
 of one, therefore in order to actually put one into your struct you have
 to declare an instance of one, thus the line:

 junk a;


 Anonymous unions are allowed and of course declare an instance instead  
 of
 a definition.

 This can definately be a little confusing at first as it's not identical
 to C/C++. I think this should go into the FAQ (if it's not already)

 Regan

Ah. Gotcha. That being the case, shouldn't the compiler complain when do this?:

Yes. I think you've found a bug.
 struct test
 {
 union junk
 { uint a;
 uint b;
 }
 }

 int main()
 {  test tv;
 tv.junk.a = 1;
 }

 But it doesn't; this program compiles and runs.

Indeed, and produces some odd (but not unexpected) results: eg.. import std.stdio; struct test { union junk { uint a; uint b; } } int main() { test tv; int padding; padding = 0; tv.junk.a = 1; tv.junk.b = 2; writef(tv.junk.a,",",tv.junk.b,",",padding,"\n"); printf("0x%X,0x%X,0x%X,0x%X\n",&tv,&tv.junk.a,&tv.junk.b,&padding); return 0; } I was expecting the 'padding' variable to be stomped on by the assignment to 'tv.junk.a' and/or 'tv.junk.b' because the struct 'tv' has reportedly got a sizeof 1 and a uint has a sizeof 4. However it seems the compiler has placed some padding between 'tv' and 'padding'. Regan
Dec 02 2004
prev sibling parent Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Geoff Hickey schrieb am Thu, 2 Dec 2004 23:11:21 +0000 (UTC):
 In article <opsieivo1m23k2f5 ally>, Regan Heath says...
you are not declaring an instance of a union, but instead the definition  
of one, therefore in order to actually put one into your struct you have  
to declare an instance of one, thus the line:

junk a;


Anonymous unions are allowed and of course declare an instance instead of  
a definition.

This can definately be a little confusing at first as it's not identical  
to C/C++. I think this should go into the FAQ (if it's not already)


 Ah. Gotcha. That being the case, shouldn't the compiler complain when do this?:

 struct test
 {
 union junk
 { uint a;
 uint b;
 }
 }

 int main()
 {  test tv;
 tv.junk.a = 1;
 }

 But it doesn't; this program compiles and runs.

Added to DStress as: http://svn.kuehne.cn/dstress/nocompile/union_12.d http://svn.kuehne.cn/dstress/nocompile/union_13.d http://svn.kuehne.cn/dstress/nocompile/union_14.d http://svn.kuehne.cn/dstress/nocompile/union_15.d Thomas -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.9.12 (GNU/Linux) iD8DBQFBsHDX3w+/yD4P9tIRApIeAKC9yYBq8ugi7iPf+ssG88+W88xv6wCfR6wc bMQY1ou7k1QqoWXWg4T2ewE= =rwRa -----END PGP SIGNATURE-----
Dec 03 2004
prev sibling parent reply "Simon Buchan" <currently no.where> writes:
On Fri, 03 Dec 2004 11:17:38 +1300, Regan Heath <regan netwin.co.nz> wrote:

<snip>
 Note: When you write:

 union junk {
    uint a;
    uint b;
 }

 you are not declaring an instance of a union, but instead the definition  
 of one, therefore in order to actually put one into your struct you have  
 to declare an instance of one, thus the line:

 junk a;


 Anonymous unions are allowed and of course declare an instance instead  
 of a definition.

 This can definately be a little confusing at first as it's not identical  
 to C/C++. I think this should go into the FAQ (if it's not already)

 Regan

Walter, if you're listening, is there any reason to not allow struct {<body>} <instance>;? Now I have nothing against forbidding defining and instancing structs at the same time, but to not allow unnamed struct instances? That's just weird. -- "Unhappy Microsoft customers have a funny way of becoming Linux, Salesforce.com and Oracle customers." - www.microsoft-watch.com: "The Year in Review: Microsoft Opens Up" "Changes/Additions -------------------------------------------------------------------------------- HL2DM released! " - HL2DM changelog "#$# % YES!" - ME
Dec 03 2004
parent "Walter" <newshound digitalmars.com> writes:
"Simon Buchan" <currently no.where> wrote in message
news:opsifsjacvjccy7t simon.homenet...
 Walter, if you're listening, is there any reason to
 not allow struct {<body>} <instance>;?

Anonymous structs make them unnecessary.
Dec 04 2004