ldln has asked for the wisdom of the Perl Monks concerning the following question:

Prob some stupid mistake, but why does sizeof give 8 and not 5. One "char" (1byte) + One "long" (4bytes) = 5?

use Win32::API; use Win32::API::Struct; use strict; use warnings; #0.41 #print Win32::API->VERSION; Win32::API::Struct->typedef('test', qw( char i; long l; )); my $Bl = Win32::API::Struct->new('test'); #8. Why not 5? print "\nSize:", $Bl->sizeof();

Replies are listed 'Best First'.
Re: Win32::API::Struct problem
by rhesa (Vicar) on Oct 27, 2006 at 00:19 UTC
    The reason is structure alignment (i.e. how the structure is stored in memory). I'd guess that it gets rounded up to the nearest DWORD boundary.

    Running your snippet with $Win32::API::DEBUG=1 reveals some detail about what's going on:

    use Win32::API; use Win32::API::Struct; $Win32::API::DEBUG = 1; Win32::API::Struct->typedef( test => qw(char i; long l;) ); my $b = Win32::API::Struct->new( 'test' ); print $b->sizeof;
    Output:
    (PM)Struct::recognize got 'i', 'char' -> 'c' (PM)Struct::recognize got 'l', 'long' -> 'l' (PM)Struct::new: got 'test' (PM)Struct::sizeof: sizeof with member(i) now = 1 (PM)Struct::sizeof: sizeof with member(l) now = 5 (PM)Struct::sizeof first=1 align=4 (PM)Struct::sizeof returning 8 8
Re: Win32::API::Struct problem
by Old_Gray_Bear (Bishop) on Oct 27, 2006 at 00:24 UTC
    I suspect that you are on an architecture that insists that a long() must begin on a word boundary (the address%4 = 0). When you inserted the char(), you moved the next available memory position off of a word boundary, and so you get the three slack-bytes inserted. If you positively must have the smallest in-memory foot-print, then order the components of your struct in order of decreasing alignment -- float/double before long before half-word before int/char/byte.

    ----
    I Go Back to Sleep, Now.

    OGB

      Size of this struct is reported as 3!?
      Win32::API::Struct->typedef('test', qw( long array[10]; char i; char z; ));
      Size of this is reported as 40 (logical, since one "long" = 4bytes * 10 = 40).
      Win32::API::Struct->typedef('test', qw( long array[10]; ));
      What is this all about?
        What is this all about?

        Looks like a bug - this one looks like it might be related to http://rt.cpan.org/Public/Bug/Display.html?id=6757 which refers you to http://www.perlmonks.org/index.pl?node_id=369601. As mentioned in the update to that perlmonks post, there seems to be some problem with the member alignment aspect of the computation - which becomes apparent when you turn on $Win32::API::DEBUG (as recommended in an earlier post). You can handle structs in Win32::API without having to resort to using Win32::API::Struct. I think that not using Win32::API::Struct is probably the best way to workaround any problems that Win32::API::Struct throws at you :-)

        Cheers,
        Rob