Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: size of C++ class question...

Author: Bruce Moreland

Date: 01:30:16 02/14/99

Go up one level in this thread



On February 14, 1999 at 02:40:01, James Robertson wrote:

>I had problems with wierd sizes too. I was going to make my book records 12
>bytes in size (64 bits for hash code, 32 for scores and stuff) but found that
>even if I declared the struct:
>
>struct BookRecord
>{
>  unsigned __int64 code;
>  int              score;
>}
>
>sizeof(BookRecord) would still = 16 bytes!!! I have no idea why, and to this day
>my book records are 16 bytes.....
>
>James

You are both getting killed by alignment stuff.  The compiler will pad
structures in such a manner that you won't have mis-aligned data if you make an
array of the things.

A 9-byte structure with an 32-bit value in it will pad to 12 bytes.  Example:

    struct {
        int i, j;
        char ch;
    } v[2];

It would be really bad if this thing were really made 9 bytes in size.  If you
tried to access v[1].i, you'd access a 32-bit value at offset 9 from the start
of the array, which isn't aligned on a 32-bit boundary.

On a pentium, you'll go very slow.  On an Alpha (21164), the compiler would
actually have to generate special code to handle this case, which would go
really slow.

So in order to protect you, the compiler pads your structure.

I don't understand the 64-bit alignment in the example in the quoted post, but
apparently the compiler is doing the same thing here.  It is trying to align the
structure so that you won't access the 64-bit thing on a 32-bit boundary, if you
have an array of them.

If you really want to make an unaligned structure, do:

    #pragma pack(1)

before the structure definition, and:

    #pragma pack()

after it.  This will prevent the compiler from adding pad bytes.

You should only do this if you have a structure that really really needs to be
small (probably because you have a huge array of them), or is written to disk.
In this case it is also a bad idea to use "int", which can change size.  It's
probably best to typedef something, I use "typedef int I32;" for Intel, for
instance.  Normally you don't care what sizeof(int) is, but when you write one
to disk, obviously you do.

Realize as well that by packing, you will pay a performance penalty.

Another issue involves the order that members are declared in a structure.  This
is a bad idea:

    struct {
        char ch1;
        int i;
        char ch2;
    } v;

Sizeof this thing should be six, you'd think, but it will actually be 12.  The
char is given one byte, but in order to avoid a misaligned access of the int, 3
pad bytes are added.  Then the int comes, which is 4 bytes, then the char, which
is another one, then three more pad bytes.  If you put the chars together:

    struct {
        char ch1;
        char ch2;
        int i;
    } v;

you'd get two pad bytes after ch2, and none at the end of the structure, so
you'd save four bytes per element.  You could put the int first, which would
cause the pad bytes to be at the end of the structure, if this is more to your
liking.

If you really wanted to save space here, this is on the of the few times that
you'd want to use "short", since this would make this structure half the size (4
bytes), at the cost of some performance, which you might not care about if you
rarely actually access the elements in the array.

bruce



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.