Thread overview
struct.sizeof is wrong when the struct contains a union
Dec 02, 2004
Geoff Hickey
Dec 02, 2004
Regan Heath
Dec 02, 2004
Geoff Hickey
Dec 02, 2004
Regan Heath
Dec 03, 2004
Thomas Kuehne
Dec 03, 2004
Simon Buchan
Dec 04, 2004
Walter
December 02, 2004
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;
}



December 02, 2004
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
December 02, 2004
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


December 02, 2004
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
December 03, 2004
-----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-----
December 03, 2004
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
December 04, 2004
"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.