www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - problem understanding struct sizes v class sizes

reply "owenm" <owen owenm.com> writes:
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.
Apr 17 2005
parent reply David L. Davis <SpottedTiger yahoo.com> writes:
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
Apr 17 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
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
Apr 17 2005
parent reply David L. Davis <SpottedTiger yahoo.com> writes:
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
Apr 17 2005
parent Paul Bonser <misterpib gmail.com> writes:
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
Apr 20 2005
prev sibling parent reply owenm <owenm_member pathlink.com> writes:
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

Apr 18 2005
parent David L. Davis <SpottedTiger yahoo.com> writes:
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
Apr 18 2005