Size of a struct - totally confused

Discussion in 'C++' started by James Gregory, Jan 30, 2004.

  1. I'm pretty sure this is non-totally-trivial enough and standard-C++ enough
    to post here, however much it may initially look like a "how do I make a
    computer game?" question, though I may be wrong.

    I'm loading a bitmap, and as I'm using Linux I've had to define
    BITMAPFILEHEADER myself (maybe better practice would be to give my version
    a new name or whatever, I dunno). Windows uses WORDs and DWORDs to
    define it, I've used some standard-size types provided by SDL (a
    graphics/sound library thing) to define it thus:

    struct BITMAPFILEHEADER
    {
    Uint16 bfType;
    Uint32 bfSize;
    Uint16 bfReserved1;
    Uint16 bfReserved2;
    Uint32 bfOffBits;
    };

    For some reason I utterly can't fathom, however, a debugger shows that my
    bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.

    Surely that should be 14?

    I then tried redefining it a couple of times:

    BITMAPFILEHEADER
    {
    Uint32 bfType; //changed from 16 to 32
    Uint32 bfSize;
    Uint16 bfReserved1;
    Uint16 bfReserved2;
    Uint32 bfOffBits;
    };

    This gives sizeof(BITMAPFILEHEADER) == 16, which is now correct.

    BITMAPFILEHEADER
    {
    Uint32 bfType;
    Uint32 bfSize;
    Uint32 bfReserved1;
    Uint32 bfReserved2;
    Uint32 bfOffBits;
    };

    This gives sizeof(BITMAPFILEHEADER) == 20, which is also correct.

    Most likely I just misunderstand something somewhere, but I've no idea
    what.

    Thanks,

    James
     
    James Gregory, Jan 30, 2004
    #1
    1. Advertising

  2. James Gregory

    Rolf Magnus Guest

    James Gregory wrote:

    > I'm pretty sure this is non-totally-trivial enough and standard-C++
    > enough to post here, however much it may initially look like a "how do
    > I make a computer game?" question, though I may be wrong.
    >
    > I'm loading a bitmap,


    You mean a .bmp file? The term "bitmap" has a different meaning outside
    the Microsoft world.

    > and as I'm using Linux I've had to define BITMAPFILEHEADER myself
    > (maybe better practice would be to give my version a new name or
    > whatever, I dunno). Windows uses WORDs and DWORDs to define it, I've
    > used some standard-size types provided by SDL (a graphics/sound
    > library thing) to define it thus:
    >
    > struct BITMAPFILEHEADER
    > {
    > Uint16 bfType;
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > For some reason I utterly can't fathom, however, a debugger shows that
    > my bitmap loader function believes that sizeof(BITMAPFILEHEADER) ==
    > 16.


    What do you mean by "believes"?

    > Surely that should be 14?


    Nope. You seem to be getting alignment. For faster access (and on many
    hardware platforms for being able to access it at all), 32bit variables
    are often alinged on a 32bit basis. So your compiler probably added two
    bytes of empty space between the first and second member to align it.

    > I then tried redefining it a couple of times:
    >
    > BITMAPFILEHEADER
    > {
    > Uint32 bfType; //changed from 16 to 32
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > This gives sizeof(BITMAPFILEHEADER) == 16, which is now correct.
    >
    > BITMAPFILEHEADER
    > {
    > Uint32 bfType;
    > Uint32 bfSize;
    > Uint32 bfReserved1;
    > Uint32 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > This gives sizeof(BITMAPFILEHEADER) == 20, which is also correct.
    >
    > Most likely I just misunderstand something somewhere, but I've no idea
    > what.


    The above shows one reason why it's never a good idea to read binary
    data directly into a struct. It's not portable. Also think what happens
    if your program will be compiled e.g. on linux/ppc. Your program will
    stop to work because of endianness problems. And as I wrote above, some
    systems can't even access unaligned memory. So better read each value
    separately, and if you want portability, consider things like
    endianness conversion.
     
    Rolf Magnus, Jan 30, 2004
    #2
    1. Advertising

  3. James Gregory

    White Wolf Guest

    James Gregory wrote:
    > I'm pretty sure this is non-totally-trivial enough and standard-C++
    > enough to post here, however much it may initially look like a "how do I
    > make a computer game?" question, though I may be wrong.
    >
    > I'm loading a bitmap, and as I'm using Linux I've had to define
    > BITMAPFILEHEADER myself (maybe better practice would be to give my
    > version a new name or whatever, I dunno). Windows uses WORDs and DWORDs
    > to
    > define it, I've used some standard-size types provided by SDL (a
    > graphics/sound library thing) to define it thus:
    >
    > struct BITMAPFILEHEADER
    > {
    > Uint16 bfType;
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?

    [SNIP]

    Not necessarily:

    bfType: 2
    Padding to get bfSize to start again on int boundary: 2
    bfSize: 4
    Res1: 2
    Res2: 2
    bfOffBits: 4

    That is 16. You may want to look at the gcc/g++ docs how to ask packing for
    a struct.

    --
    WW aka Attila
    :::
    Be bold in what you stand for and careful what you fall for.
     
    White Wolf, Jan 30, 2004
    #3
  4. James Gregory

    Phlip Guest

    James Gregory wrote:

    > I'm pretty sure this is non-totally-trivial enough and standard-C++ enough
    > to post here, however much it may initially look like a "how do I make a
    > computer game?" question, though I may be wrong.


    Relax - padding is on-topic.

    > I'm loading a bitmap, and as I'm using Linux I've had to define
    > BITMAPFILEHEADER myself (maybe better practice would be to give my version
    > a new name or whatever, I dunno).


    There must be a graphics library you can use. Start with ImageMagick.

    > Windows uses WORDs and DWORDs to
    > define it, I've used some standard-size types provided by SDL (a
    > graphics/sound library thing) to define it thus:
    >
    > struct BITMAPFILEHEADER
    > {
    > Uint16 bfType;
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?


    Plenty of hardware works best reading integers aligned on quad-word
    boundaries. Put another way, the address of a bfSize can evenly divide by 4
    with 0 remainder.

    The compiler inserted an invisible 16-bit padding element between bfType and
    bfSize. Compilers are allowed to do this, and required to give notice how
    they do it. It's "implementation specified".

    Now ask the documentation or forum that covers your compiler how to turn it
    off. They will probably point out a library that already reads BMP files,
    too.

    --
    Phlip
    http://www.xpsd.org/cgi-bin/wiki?TestFirstUserInterfaces
     
    Phlip, Jan 30, 2004
    #4
  5. "James Gregory" <> wrote...
    > I'm pretty sure this is non-totally-trivial enough and standard-C++ enough
    > to post here, however much it may initially look like a "how do I make a
    > computer game?" question, though I may be wrong.
    >
    > I'm loading a bitmap, and as I'm using Linux I've had to define
    > BITMAPFILEHEADER myself (maybe better practice would be to give my version
    > a new name or whatever, I dunno). Windows uses WORDs and DWORDs to
    > define it, I've used some standard-size types provided by SDL (a
    > graphics/sound library thing) to define it thus:
    >
    > struct BITMAPFILEHEADER
    > {
    > Uint16 bfType;
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?
    >
    > I then tried redefining it a couple of times:
    >
    > BITMAPFILEHEADER
    > {
    > Uint32 bfType; //changed from 16 to 32
    > Uint32 bfSize;
    > Uint16 bfReserved1;
    > Uint16 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > This gives sizeof(BITMAPFILEHEADER) == 16, which is now correct.
    >
    > BITMAPFILEHEADER
    > {
    > Uint32 bfType;
    > Uint32 bfSize;
    > Uint32 bfReserved1;
    > Uint32 bfReserved2;
    > Uint32 bfOffBits;
    > };
    >
    > This gives sizeof(BITMAPFILEHEADER) == 20, which is also correct.
    >
    > Most likely I just misunderstand something somewhere, but I've no idea
    > what.


    Sizes of object can include so called "padding" to ensure that the objects
    in an array begin at a particular multiple of bytes boundary. For example,
    on some platforms it should be multiple of 4 to make memory access faster.
    14 is not multiple of 4, so it chooses the next larger multiple of 4.

    There probably is a [compiler-specific] way to control the padding or the
    alignment factor, consult your compiler documentation to find out how to
    do that.

    Victor
     
    Victor Bazarov, Jan 30, 2004
    #5
  6. James Gregory wrote:

    > I'm pretty sure this is non-totally-trivial enough and standard-C++ enough
    > to post here, however much it may initially look like a "how do I make a
    > computer game?" question, though I may be wrong.
    >
    > I'm loading a bitmap, and as I'm using Linux I've had to define
    > BITMAPFILEHEADER myself (maybe better practice would be to give my version
    > a new name or whatever, I dunno). Windows uses WORDs and DWORDs to
    > define it, I've used some standard-size types provided by SDL (a
    > graphics/sound library thing) to define it thus:
    >


    #include<stdint.h>

    > struct BITMAPFILEHEADER {
    > uint16_t bfType;
    > uint32_t bfSize;
    > uint16_t bfReserved1;
    > uint16_t bfReserved2;
    > uint32_t bfOffBits;
    > };
    >
    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?


    Apparently, your compiler and/or machine architecture
    requires unint32_t alignment on 32 bit word boundaries.

    Try this:

    struct X {
    int i;
    double x;
    int j;
    };

    and this:

    struct Y {
    double x;
    int i;
    int j;
    };

    A double probably requires a 64 bit word alignment.

    If this is important to you, you should try place the objects
    with the coarsest alignment requirements first.
     
    E. Robert Tisdale, Jan 31, 2004
    #6
  7. James Gregory

    Default User Guest

    James Gregory wrote:

    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?



    http://www.eskimo.com/~scs/C-faq/q2.13.html



    Brian Rodenborn
     
    Default User, Jan 31, 2004
    #7
  8. James Gregory wrote:
    ....
    > For some reason I utterly can't fathom, however, a debugger shows that my
    > bitmap loader function believes that sizeof(BITMAPFILEHEADER) == 16.
    >
    > Surely that should be 14?


    So many people have already answered why it's not. However - try this:

    #pragma pack(1)
    struct BITMAPFILEHEADER
    {
    Uint16 bfType;
    Uint32 bfSize;
    Uint16 bfReserved1;
    Uint16 bfReserved2;
    Uint32 bfOffBits;
    };
    #pragma pack()

    The "pack" pragma is not standard but I have yet to meet a compiler that
    does not implement it (in some way).

    ....
     
    Gianni Mariani, Jan 31, 2004
    #8
  9. James Gregory

    Jack Klein Guest

    On Fri, 30 Jan 2004 23:50:33 GMT, "Phlip" <> wrote
    in comp.lang.c++:

    [snip]


    > Plenty of hardware works best reading integers aligned on quad-word
    > boundaries. Put another way, the address of a bfSize can evenly divide by 4
    > with 0 remainder.
    >
    > The compiler inserted an invisible 16-bit padding element between bfType and
    > bfSize. Compilers are allowed to do this, and required to give notice how
    > they do it. It's "implementation specified".


    Both the C and C++ standards define the term "implementation-defined",
    not "implementation specified". And both spell it with the hyphen.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Jan 31, 2004
    #9
  10. James Gregory

    Jack Klein Guest

    On Fri, 30 Jan 2004 16:07:58 -0800, "E. Robert Tisdale"
    <> wrote in comp.lang.c++:

    > James Gregory wrote:
    >
    > > I'm pretty sure this is non-totally-trivial enough and standard-C++ enough
    > > to post here, however much it may initially look like a "how do I make a
    > > computer game?" question, though I may be wrong.
    > >
    > > I'm loading a bitmap, and as I'm using Linux I've had to define
    > > BITMAPFILEHEADER myself (maybe better practice would be to give my version
    > > a new name or whatever, I dunno). Windows uses WORDs and DWORDs to
    > > define it, I've used some standard-size types provided by SDL (a
    > > graphics/sound library thing) to define it thus:
    > >

    >
    > #include<stdint.h>


    Non standard in C++. Be all right if you were posting in comp.lang.c,
    though.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Jan 31, 2004
    #10
  11. On Fri, 30 Jan 2004 23:29:26 +0000, James Gregory wrote:

    > This gives sizeof(BITMAPFILEHEADER) == 20, which is also correct.
    >
    > Most likely I just misunderstand something somewhere, but I've no idea
    > what.
    >
    > Thanks,


    Wow, thanks for all the replies, most helpful.

    James
     
    James Gregory, Jan 31, 2004
    #11
  12. EventHelix.com, Jan 31, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,405
    Chris Fogelklou
    Apr 20, 2004
  2. stef mientki

    LEGB rule, totally confused ...

    stef mientki, Aug 14, 2007, in forum: Python
    Replies:
    6
    Views:
    679
    Diez B. Roggisch
    Aug 15, 2007
  3. Lloyd Sheen

    Totally confused

    Lloyd Sheen, Mar 6, 2008, in forum: ASP .Net
    Replies:
    5
    Views:
    358
    Lloyd Sheen
    Mar 28, 2008
  4. Giampaolo Rodola'
    Replies:
    17
    Views:
    1,078
    John Machin
    Jan 18, 2009
  5. eBob.com

    Newbie Totally Confused

    eBob.com, Feb 3, 2008, in forum: Javascript
    Replies:
    2
    Views:
    103
Loading...

Share This Page