Compiler specific?: struct with wrong sizeof

C

Chameleon

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
 
I

Ian Collins

Chameleon said:
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.
 
C

Chameleon

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

No. it's padding.

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!
 
M

Markus Svilans

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

No. it's padding.

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.
 
C

Chameleon

Chameleon said:
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?
 
S

Sylvester Hesp

Chameleon said:
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
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Chameleon said:
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.
 
M

Michael DOUBEZ

Julián Albo a écrit :
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.
 
G

Grizlyk

Markus said:
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;
};
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top