Compiler specific?: struct with wrong sizeof

Discussion in 'C++' started by Chameleon, Jan 14, 2007.

  1. Chameleon

    Chameleon Guest

    I have a TGA image header struct.
    TGA has 18 bytes header, so the C struct too.

    why this return 20?
    sizeof(TGAHeader)


    I saw this in many structs. I believe compiler round up the size to 4
    multiple.

    Compiler is mingw gcc. Why this happens?
    how can I pass the size in fread without hardcode the header size?


    thanks
     
    Chameleon, Jan 14, 2007
    #1
    1. Advertising

  2. Chameleon

    Ian Collins Guest

    Chameleon wrote:
    > I have a TGA image header struct.
    > TGA has 18 bytes header, so the C struct too.
    >
    > why this return 20?
    > sizeof(TGAHeader)
    >

    The compiler is free to insert padding to ensure correct alignment of
    the struct members.

    >
    > I saw this in many structs. I believe compiler round up the size to 4
    > multiple.
    >

    No. it's padding.

    > Compiler is mingw gcc. Why this happens?
    > how can I pass the size in fread without hardcode the header size?
    >

    You simply can't. Unless your platform has a means of packing
    structures. Even it if does, the cost due to misaligned access may be
    to high to justify their use.

    --
    Ian Collins.
     
    Ian Collins, Jan 14, 2007
    #2
    1. Advertising

  3. Chameleon

    Chameleon Guest

    > Chameleon wrote:
    >> I have a TGA image header struct.
    >> TGA has 18 bytes header, so the C struct too.
    >>
    >> why this return 20?
    >> sizeof(TGAHeader)
    >>

    > The compiler is free to insert padding to ensure correct alignment of
    > the struct members.
    >
    >> I saw this in many structs. I believe compiler round up the size to 4
    >> multiple.
    >>

    > No. it's padding.
    >
    >> Compiler is mingw gcc. Why this happens?
    >> how can I pass the size in fread without hardcode the header size?
    >>

    > You simply can't. Unless your platform has a means of packing
    > structures. Even it if does, the cost due to misaligned access may be
    > to high to justify their use.



    Whow! How I miss this until now?!
    I fread many structures in the past!
    I am scaring to see my old code now!...


    thanks!
     
    Chameleon, Jan 14, 2007
    #3
  4. Ian Collins wrote:
    > Chameleon wrote:
    > > I have a TGA image header struct.
    > > TGA has 18 bytes header, so the C struct too.
    > >
    > > why this return 20?
    > > sizeof(TGAHeader)
    > >

    > The compiler is free to insert padding to ensure correct alignment of
    > the struct members.
    >
    > >
    > > I saw this in many structs. I believe compiler round up the size to 4
    > > multiple.
    > >

    > No. it's padding.
    >
    > > Compiler is mingw gcc. Why this happens?
    > > how can I pass the size in fread without hardcode the header size?
    > >

    > You simply can't. Unless your platform has a means of packing
    > structures. Even it if does, the cost due to misaligned access may be
    > to high to justify their use.


    Properly packed structures can be crucial when reading data from binary
    file headers, as the OP appears to be doing with the TGAHeader
    structure.

    Your compiler may have a "#pragma option" feature that you can use to
    wrap your structure definition, to enforce the byte alignment you want.
    You have to refer to your documentation for details.

    For example, in Borland C++ Builder 6, I would use:

    #include <iostream>

    #pragma option push -a1 // set 1 byte alignment
    struct test_data
    {
    char c;
    int value;
    };
    #pragma option pop // restore original byte alignment

    // Exactly the same structure, but using default alignment
    struct test_data2
    {
    char c;
    int value;
    };

    int main(int argc, char* argv[])
    {
    using namespace std;
    cout << "Using 1-byte alignment:" << endl;
    cout << "sizeof(test_data) == ";
    cout << sizeof(test_data) << endl << endl;
    cout << "Using default alignment:" << endl;
    cout << "sizeof(test_data2) == ";
    cout << sizeof(test_data2) << endl;
    return 0;
    }

    On my computer, the output looks like this:

    Using 1-byte alignment:
    sizeof(test_data) == 5

    Using default alignment:
    sizeof(test_data2) == 8

    You can see that with the #pragma in place, sizeof(test_data) is 5, as
    you may expect from examining the contents of test_data.

    In contrast, sizeof(test_data2) is 8, even though the structures have
    identical contents. This is because the compiler pads the fields to
    make them line up on 4-byte boundaries in this case.

    Your results may be different, depending on which platform you are
    using.

    Regards,
    Markus.
     
    Markus Svilans, Jan 14, 2007
    #4
  5. Chameleon

    Chameleon Guest

    > Chameleon wrote:
    >> I have a TGA image header struct.
    >> TGA has 18 bytes header, so the C struct too.
    >>
    >> why this return 20?
    >> sizeof(TGAHeader)
    >>

    > The compiler is free to insert padding to ensure correct alignment of
    > the struct members.



    What means "correct alignment of the struct members"?
    Why this thing exists?
     
    Chameleon, Jan 15, 2007
    #5
  6. "Chameleon" <> wrote in message
    news:eoek3o$qc3$...
    >> Chameleon wrote:
    >>> I have a TGA image header struct.
    >>> TGA has 18 bytes header, so the C struct too.
    >>>
    >>> why this return 20?
    >>> sizeof(TGAHeader)
    >>>

    >> The compiler is free to insert padding to ensure correct alignment of
    >> the struct members.

    >
    >
    > What means "correct alignment of the struct members"?
    > Why this thing exists?


    It means that members of the struct are properly aligned by the compiler. A
    32 bits int, for example, is usually aligned on a 4 byte boundary. This is
    because on most architectures aligned reads/writes are faster than
    misaligned reads/writes, and on some it is even mandatory (a misaligned
    read/write can cause some kind of access violation).

    Therefore a struct { char c; int i; }; is usually 8 bytes (depending on the
    architecture really) because i is aligned on 4 bytes, causing 3 bytes
    padding to be used between c and i. Note that struct { int i; char c; }; is
    usually also 8 bytes on such an architecture - if you use the struct in an
    array, the member 'i' of the second element needs to be 4-byte aligned as
    well, so that's why in this case there's a 3 byte padding at the end of the
    struct.

    - Sylvester
     
    Sylvester Hesp, Jan 15, 2007
    #6
  7. Chameleon wrote:

    >> The compiler is free to insert padding to ensure correct alignment of
    >> the struct members.

    > What means "correct alignment of the struct members"?


    Whatever the compiler designers decided. In some cases, the processor has
    alignment restrictions for 2 or 4 byte data types and is convenient that
    the access to struct members can be done with one instruction. In others,
    there are no absolute restriction but access to data aligned is faster, and
    the intended users of the compiler want speed.

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jan 15, 2007
    #7
  8. Julián Albo a écrit :
    > Chameleon wrote:
    >
    >>> The compiler is free to insert padding to ensure correct alignment of
    >>> the struct members.

    >> What means "correct alignment of the struct members"?

    >
    > Whatever the compiler designers decided. In some cases, the processor has
    > alignment restrictions for 2 or 4 byte data types and is convenient that
    > the access to struct members can be done with one instruction. In others,
    > there are no absolute restriction but access to data aligned is faster, and
    > the intended users of the compiler want speed.
    >


    And in other cases, it can yield corrupted reading i.e. if your
    plateform doesn't feature a MMU.
     
    Michael DOUBEZ, Jan 15, 2007
    #8
  9. Chameleon

    Grizlyk Guest

    Markus Svilans wrote:

    > > > Chameleon wrote:
    > > > Compiler is mingw gcc. Why this happens?

    >
    > Your compiler may have a "#pragma option" feature that you can use to
    > wrap your structure definition, to enforce the byte alignment you want.
    > You have to refer to your documentation for details.
    >


    Also try: info gcc, C externtions, Type Attributes,

    struct my_unpacked_struct
    {
    char c;
    int i;
    };

    struct __attribute__ ((__packed__)) my_packed_struct
    {
    char c;
    int i;
    struct my_unpacked_struct s;
    };
     
    Grizlyk, Jan 15, 2007
    #9
    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. Derek
    Replies:
    7
    Views:
    24,369
    Ron Natalie
    Oct 14, 2004
  2. Trevor

    sizeof(str) or sizeof(str) - 1 ?

    Trevor, Apr 3, 2004, in forum: C Programming
    Replies:
    9
    Views:
    650
    CBFalconer
    Apr 10, 2004
  3. Chris Fogelklou
    Replies:
    36
    Views:
    1,405
    Chris Fogelklou
    Apr 20, 2004
  4. Vinu
    Replies:
    13
    Views:
    1,459
    Lawrence Kirby
    May 12, 2005
  5. blufox

    sizeof( int ) != sizeof( void * )

    blufox, May 22, 2006, in forum: C Programming
    Replies:
    2
    Views:
    567
    Joe Smith
    May 22, 2006
Loading...

Share This Page