Thread overview
problem understanding struct sizes v class sizes
Apr 17, 2005
owenm
Apr 17, 2005
David L. Davis
Apr 18, 2005
Regan Heath
Apr 18, 2005
David L. Davis
Apr 21, 2005
Paul Bonser
Apr 18, 2005
owenm
Apr 18, 2005
David L. Davis
April 17, 2005
Would some kind soul please explain the output from the following small (v0.121) program?  I'm clearly missing something very basic in understanding this.

#import std.stdio;
#
#struct Struct1 { int x, y; }
#struct Struct2 { Struct1 pos1, pos2; }
#class  Class1  { Struct1 pos1, pos2; }
#
#int main() {
# writefln("sizeof [int] is [%d]",int.sizeof);
# writefln("sizeof [Struct1] is [%d]",Struct1.sizeof);
# writefln("sizeof [Struct2] is [%d]",Struct2.sizeof);
# writefln("sizeof [Class1]  is [%d]",Class1.sizeof);
# return 0;
#}

Output is:

sizeof [int] is [4]
sizeof [Struct1] is [8]
sizeof [Struct2] is [16]
sizeof [Class1]  is [4]

Why is the size of Class1 not also equal to 16?

many thanks,
owenm.


April 17, 2005
In article <d3ugb7$2c0f$1@digitaldaemon.com>, owenm says...
>
>Would some kind soul please explain the output from the following small (v0.121) program?  I'm clearly missing something very basic in understanding this.
>
>#import std.stdio;
>#
>#struct Struct1 { int x, y; }
>#struct Struct2 { Struct1 pos1, pos2; }
>#class  Class1  { Struct1 pos1, pos2; }
>#
>#int main() {
># writefln("sizeof [int] is [%d]",int.sizeof);
># writefln("sizeof [Struct1] is [%d]",Struct1.sizeof);
># writefln("sizeof [Struct2] is [%d]",Struct2.sizeof);
># writefln("sizeof [Class1]  is [%d]",Class1.sizeof);
># return 0;
>#}
>
>Output is:
>
>sizeof [int] is [4]
>sizeof [Struct1] is [8]
>sizeof [Struct2] is [16]
>sizeof [Class1]  is [4]
>
>Why is the size of Class1 not also equal to 16?
>
>many thanks,
>owenm.
>

Check out the thread for the answer why? http://www.digitalmars.com/d/archives/27280.html

Here's a little change to your D code that seems to work fine:

# import std.stdio;
#
# struct Struct1 { int x, y; }
# struct Struct2 { Struct1 pos1, pos2; }
# class  Class1
# {
#     Struct1  pos1, pos2;
#     public uint length() { return this.classinfo.init.length; }
# }
#
# int main()
# {
#     // Need to create before getting it's memory size.
#     Class1 oClass1 = new Class1;
#
#     writefln("sizeof [int]     is [%d]", int.sizeof);
#     writefln("sizeof [Struct1] is [%d]", Struct1.sizeof);
#     writefln("sizeof [Struct2] is [%d]", Struct2.sizeof);
#
#     // sizeof of Class Reference
#     writefln("sizeof [Class1 Reference] is [%d]", oClass1.sizeof);
#     // sizeof the Class itself
#     writefln("sizeof [Class1]  is [%d]", oClass1.length());
#
#     return 0;
# }

Output is:

sizeof [int]     is [4]
sizeof [Struct1] is [8]
sizeof [Struct2] is [16]
sizeof [Class1 Reference] is [4]
sizeof [Class1]  is [24]

Hope this helps.

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
April 18, 2005
On Sun, 17 Apr 2005 23:30:31 +0000 (UTC), David L. Davis <SpottedTiger@yahoo.com> wrote:
> In article <d3ugb7$2c0f$1@digitaldaemon.com>, owenm says...
>>
>> Would some kind soul please explain the output from the following small
>> (v0.121) program?  I'm clearly missing something very basic in understanding
>> this.
>>
>> #import std.stdio;
>> #
>> #struct Struct1 { int x, y; }
>> #struct Struct2 { Struct1 pos1, pos2; }
>> #class  Class1  { Struct1 pos1, pos2; }
>> #
>> #int main() {
>> # writefln("sizeof [int] is [%d]",int.sizeof);
>> # writefln("sizeof [Struct1] is [%d]",Struct1.sizeof);
>> # writefln("sizeof [Struct2] is [%d]",Struct2.sizeof);
>> # writefln("sizeof [Class1]  is [%d]",Class1.sizeof);
>> # return 0;
>> #}
>>
>> Output is:
>>
>> sizeof [int] is [4]
>> sizeof [Struct1] is [8]
>> sizeof [Struct2] is [16]
>> sizeof [Class1]  is [4]
>>
>> Why is the size of Class1 not also equal to 16?
>>
>> many thanks,
>> owenm.
>>
>
> Check out the thread for the answer why?
> http://www.digitalmars.com/d/archives/27280.html
>
> Here's a little change to your D code that seems to work fine:
>
> # import std.stdio;
> #
> # struct Struct1 { int x, y; }
> # struct Struct2 { Struct1 pos1, pos2; }
> # class  Class1
> # {
> #     Struct1  pos1, pos2;
> #     public uint length() { return this.classinfo.init.length; }
> # }
> #
> # int main()
> # {
> #     // Need to create before getting it's memory size.
> #     Class1 oClass1 = new Class1;
> #
> #     writefln("sizeof [int]     is [%d]", int.sizeof);
> #     writefln("sizeof [Struct1] is [%d]", Struct1.sizeof);
> #     writefln("sizeof [Struct2] is [%d]", Struct2.sizeof);
> #
> #     // sizeof of Class Reference
> #     writefln("sizeof [Class1 Reference] is [%d]", oClass1.sizeof);
> #     // sizeof the Class itself
> #     writefln("sizeof [Class1]  is [%d]", oClass1.length());
> #
> #     return 0;
> # }
>
> Output is:
>
> sizeof [int]     is [4]
> sizeof [Struct1] is [8]
> sizeof [Struct2] is [16]
> sizeof [Class1 Reference] is [4]
> sizeof [Class1]  is [24]
>
> Hope this helps.

This behaviour seems broken/odd/wrong to me.

Assuming:
#class Class1 { Struct1 pos1, pos2; }
#void main() { Class1 foo = new Class1(); }

'Class1' is a class definition for an instance (not a reference) it's size should be some value which is most certainly (in this case) 16 or larger (if you want to take into account the vtable etc).

The heap memory allocated by the "new Class1()" call would be the same size as 'Class1'.

'foo' is a class reference on the stack, it's size should be 4 (or perhaps 8 on 64 bit systems).

I assume this odd behaviour is due to the fact that we cannot do anything useful with the size of the class definition? or can we?

Regan
April 18, 2005
In article <opspekhzh323k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>This behaviour seems broken/odd/wrong to me.
>
>Assuming:
>#class Class1 { Struct1 pos1, pos2; }
>#void main() { Class1 foo = new Class1(); }
>
>'Class1' is a class definition for an instance (not a reference) it's size should be some value which is most certainly (in this case) 16 or larger (if you want to take into account the vtable etc).
>
>The heap memory allocated by the "new Class1()" call would be the same size as 'Class1'.
>
>'foo' is a class reference on the stack, it's size should be 4 (or perhaps 8 on 64 bit systems).
>
>I assume this odd behaviour is due to the fact that we cannot do anything useful with the size of the class definition? or can we?
>
>Regan

Ragan I'm with you, it really doesn't look like Class1.sizeof gets anything use.

After looking into this a little more, it appears that a new class doesn't have to be created to get the same results. As the code below shows:

# import std.stdio;
#
# struct Struct1 { int x, y; }
# struct Struct2 { Struct1 pos1, pos2; }
# class  Class1  { Struct1 pos1, pos2; }
#
# int main()
# {
#     writefln("sizeof [int]     is [%d]", int.sizeof);
#     writefln("sizeof [Struct1] is [%d]", Struct1.sizeof);
#     writefln("sizeof [Struct2] is [%d]", Struct2.sizeof);
#     writefln("sizeof [Class1 Reference] is [%d]", Class1.sizeof);
#     writefln("sizeof [Class1]  is [%d]", Class1.classinfo.init.length);
#     return 0;
# }

Output is:

sizeof [int]     is [4]
sizeof [Struct1] is [8]
sizeof [Struct2] is [16]
sizeof [Class1 Reference] is [4]
sizeof [Class1]  is [24]

The Class1.classinfo.init.length calls seems to be giving the total size of the local variables and user-defined-types (udt), but not the size of any functions. Which I guess should be in the vtable, but I haven't figured how to get the size of the functions...I pretty bad at using pointers, much less follow where they go. :P Here's use more code I used to look at the vtable (pointer address in this case).

# private import std.stdio;
#
# struct Struct1 { int x, y; }
# struct Struct2 { Struct1 pos1, pos2; }
# class  Class1
# {
#     Struct1 pos1, pos2;
#     ulong l;  // added 8 more bytes
#     private void dummy() { }
# }
#
# class  Empty { }
#
# void main()
# {
#     with( Object.classinfo )
#        displayInfo( name, init.length, vtbl );
#
#     with( Empty.classinfo )
#        displayInfo( name, init.length, vtbl );
#
#     with( Class1.classinfo )
#        displayInfo( name, init.length, vtbl );
# }
#
# void displayInfo( in char[] s, in uint length, in void *[] vtbl )
# {
#     writefln("sizeof [%s Class] is [%d]", s, length);
#     for ( int i = 0; i < vtbl[].length; i++ )
#     {
#         writefln( "vtbl[%d]=%d, vtbl[%d].sizeof=%d",
#                    i, vtbl[i], i, vtbl[i].sizeof ) ;
#     }
#     writefln();
# }

output:
sizeof [Object Class] is [8]
vtbl[0]=4132e8, vtbl[0].sizeof=4
vtbl[1]=4021f4, vtbl[1].sizeof=4
vtbl[2]=40220c, vtbl[2].sizeof=4
vtbl[3]=402218, vtbl[3].sizeof=4
vtbl[4]=40221c, vtbl[4].sizeof=4
vtbl[5]=402224, vtbl[5].sizeof=4

sizeof [Empty Class] is [8]
vtbl[0]=413110, vtbl[0].sizeof=4
vtbl[1]=4021f4, vtbl[1].sizeof=4
vtbl[2]=40220c, vtbl[2].sizeof=4
vtbl[3]=402218, vtbl[3].sizeof=4
vtbl[4]=40221c, vtbl[4].sizeof=4
vtbl[5]=402224, vtbl[5].sizeof=4

sizeof [Class1 Class] is [32]
vtbl[0]=4130a8, vtbl[0].sizeof=4
vtbl[1]=4021f4, vtbl[1].sizeof=4
vtbl[2]=40220c, vtbl[2].sizeof=4
vtbl[3]=402218, vtbl[3].sizeof=4
vtbl[4]=40221c, vtbl[4].sizeof=4
vtbl[5]=402224, vtbl[5].sizeof=4

It looks like I have much more to learn in this area myself. If anyone could give some insight I'd be thankful.

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
April 18, 2005
Thanks for the explanation on classinfo.init.length, but it leads to another question.  Why is the length of Class1 24 and not 16?

Moreover, consider the following definitions:

#struct point { int x, y; }

#struct Struct1 { int x, y, w, h; }
#struct Struct2 { point p1, point p2; }
#class  Class1  { int x, y, w, h; }
#class  Class2  { point p1, point p2; }

I would expect to be able to cast an instance of any one of Struct1, Struct2, Class2, Class2 into an instance of any one of Struct1, Struct2, Class1, Class2 regardless of whether any member functions are defined, and with all 4 data structures having a length of 16 (4x4).

Am I wrong to have expected to be able to do this?  If the length of the class instances is 24 then a cast is out of the question.

thanks,
owenm.


In article <d3urin$2kp7$1@digitaldaemon.com>, David L. Davis says...
>Check out the thread for the answer why? http://www.digitalmars.com/d/archives/27280.html
>
>Here's a little change to your D code that seems to work fine:
>
># import std.stdio;
>#
># struct Struct1 { int x, y; }
># struct Struct2 { Struct1 pos1, pos2; }
># class  Class1
># {
>#     Struct1  pos1, pos2;
>#     public uint length() { return this.classinfo.init.length; }
># }
>#
># int main()
># {
>#     // Need to create before getting it's memory size.
>#     Class1 oClass1 = new Class1;
>#
>#     writefln("sizeof [int]     is [%d]", int.sizeof);
>#     writefln("sizeof [Struct1] is [%d]", Struct1.sizeof);
>#     writefln("sizeof [Struct2] is [%d]", Struct2.sizeof);
>#
>#     // sizeof of Class Reference
>#     writefln("sizeof [Class1 Reference] is [%d]", oClass1.sizeof);
>#     // sizeof the Class itself
>#     writefln("sizeof [Class1]  is [%d]", oClass1.length());
>#
>#     return 0;
># }
>
>Output is:
>
>sizeof [int]     is [4]
>sizeof [Struct1] is [8]
>sizeof [Struct2] is [16]
>sizeof [Class1 Reference] is [4]
>sizeof [Class1]  is [24]
>
>Hope this helps.
>
>David L.
>
>-------------------------------------------------------------------
>"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
>-------------------------------------------------------------------
>
>MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html


April 18, 2005
In article <d40ac6$vk4$1@digitaldaemon.com>, owenm says...
>
>Thanks for the explanation on classinfo.init.length, but it leads to another question.  Why is the length of Class1 24 and not 16?
>
>...
>
>thanks,
>owenm.

At this point (I'm still learning more about D's classes), I would dare to guess that since all Classes have the Object Class as their Base Class, that the additional 8 bytes are from Object.classinfo.init.length the size of the Object Class being included (which I sort of danced around in my second post to Regan), but I could be wrong.

Also, it might be helpful to take a close look at the "C:\dmd\phobos\object.d" file, because it could add some insight into the Object Class.

Please, let me know if you find anything new, in the mean time I'll continue looking into this a little bit more, but I'm hoping that one of the more seasoned D class experts would enlighten us both more about this area.

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
April 21, 2005
David L. Davis wrote:

> Output is:
> 
> sizeof [int]     is [4]
> sizeof [Struct1] is [8]
> sizeof [Struct2] is [16]
> sizeof [Class1 Reference] is [4]
> sizeof [Class1]  is [24]

It is also interesting to note that the actual memory space taken up by Class1 is 32 bytes. D only allocates objects in multiples of 4 bytes, and there's some hidden fields that it doesn't tell us about.

An empty class and a class with a single int have size 8 and 12, respectively, but both take 16 bytes in memory.

Quite interesting stuff...

-- 
-PIB

--
"C++ also supports the notion of *friends*: cooperative classes that
are permitted to see each other's private parts." - Grady Booch