struct packing error
typedef struct
{
char header[4]; // 4 bytes
short version; // 2 bytes
short flags; // 2 bytes
short compression; // 2 bytes
short modtime; // 2 bytes
short moddate; // 2 bytes
long crc; // 4 bytes
long compressedsize; // 4 bytes
long uncompressedsize; // 4 bytes
short filenamelength; // 2 bytes
short extrafieldlength; // 2 bytes
} xf_file_header;
could anyone tell me why sizeof(xf_file_header) returns 32 and not 30 like it is supposed to.
"Don''t make me come down there..." -GOD
"Don't make me come down there..." -GOD
i''m assuming your using VC++. the default structure packing size is either 4/8 bytes. to override the default packing size provide the following code.
#pragma pack(1) // 1-byte structure packing.typedef struct {// whatever members.} STRUCTURE;#pragma pack() // return to default packing.
To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
January 23, 2001 02:37 AM
some day I''ll bother to register.. I guess
I expect you got your ''30 like it is supposed to'' by counting the number of bytes in each item. However, most compilers add extra bytes into structures to force items to be aligned on particular addresses.
This is because some CPUs access certain types of data if it''s aligned correctly (eg: a long word may be faster to access if its address is evenly divisible by 4.) Some CPUs can''t access data on particular byte alignments, as well. (I can''t tell you details, because I''ve never been interested enough to memorise it, but it came up a bit when doing assembler programming as something to watch out for.) (Well, it''s one reason that I''m aware of with at least some compilers - I''m prepared to accept the existance of other possibilities.)
My first guess (and it''s just a random guess) is that you have a series of 2 byte items that add to a total of 10 bytes. Moving another 2 byte item there _might_ change the alignment, so it only takes 30 bytes. Of course, there''s actually a good chance that it won''t help anyway, because the compiler may round all alignments to 4 bytes and be rearranging things as small as possible.
I''m not convinced it''s worth obsessing about, anyay. If you always use ''sizeof'' rather than counting the bytes, your code will work. And even when your program runs on a shiny new processor with different memory restrictions, your code won''t break. (Assumptions about things like that are _bad_ and should never be done.) The OS routines for managing memory allocations are another factor - even if ''sizeof'' says you have a 30 byte structure, that doesn''t include OS overhead for memory allocations. To find that out, you need to read the docs for your OS, as well as your compiler.
If you''re using a 1/2 way decent compiler, by and large you can trust it. Compiler authors spend a lot of time working on these details, and there are usually good reasons for needing to add extra padding bytes to a structure. (Selection of a 1/2 way decent compiler is left as an exercise for the reader
If you''re losing a lot of memory (eg, instead of 2 bytes, there were 10 bytes of padding) and you''re planning on allocating a million or so of these structures, it may be worth looking into what the compiler is actually doing, and seeing if the structure members can be rearranged in a more space efficient manner. Most compilers have reasonable documentation, and there ought to be something buried away in there.
Incidentally, this is why just dumping a structure to a file tends to be a very bad thing - usually it will seem to work, but it can make your files dependant on the compiler used to compile the program reading the file, and details such as the CPU the program was running on - and you can''t rearrange the structure without breaking things.
quote:
Original post by Ecco2000
typedef struct
{
char header[4]; // 4 bytes
short version; // 2 bytes
short flags; // 2 bytes
short compression; // 2 bytes
short modtime; // 2 bytes
short moddate; // 2 bytes
long crc; // 4 bytes
long compressedsize; // 4 bytes
long uncompressedsize; // 4 bytes
short filenamelength; // 2 bytes
short extrafieldlength; // 2 bytes
} xf_file_header;
could anyone tell me why sizeof(xf_file_header) returns 32 and not 30 like it is supposed to.
I expect you got your ''30 like it is supposed to'' by counting the number of bytes in each item. However, most compilers add extra bytes into structures to force items to be aligned on particular addresses.
This is because some CPUs access certain types of data if it''s aligned correctly (eg: a long word may be faster to access if its address is evenly divisible by 4.) Some CPUs can''t access data on particular byte alignments, as well. (I can''t tell you details, because I''ve never been interested enough to memorise it, but it came up a bit when doing assembler programming as something to watch out for.) (Well, it''s one reason that I''m aware of with at least some compilers - I''m prepared to accept the existance of other possibilities.)
My first guess (and it''s just a random guess) is that you have a series of 2 byte items that add to a total of 10 bytes. Moving another 2 byte item there _might_ change the alignment, so it only takes 30 bytes. Of course, there''s actually a good chance that it won''t help anyway, because the compiler may round all alignments to 4 bytes and be rearranging things as small as possible.
I''m not convinced it''s worth obsessing about, anyay. If you always use ''sizeof'' rather than counting the bytes, your code will work. And even when your program runs on a shiny new processor with different memory restrictions, your code won''t break. (Assumptions about things like that are _bad_ and should never be done.) The OS routines for managing memory allocations are another factor - even if ''sizeof'' says you have a 30 byte structure, that doesn''t include OS overhead for memory allocations. To find that out, you need to read the docs for your OS, as well as your compiler.
If you''re using a 1/2 way decent compiler, by and large you can trust it. Compiler authors spend a lot of time working on these details, and there are usually good reasons for needing to add extra padding bytes to a structure. (Selection of a 1/2 way decent compiler is left as an exercise for the reader
If you''re losing a lot of memory (eg, instead of 2 bytes, there were 10 bytes of padding) and you''re planning on allocating a million or so of these structures, it may be worth looking into what the compiler is actually doing, and seeing if the structure members can be rearranged in a more space efficient manner. Most compilers have reasonable documentation, and there ought to be something buried away in there.
Incidentally, this is why just dumping a structure to a file tends to be a very bad thing - usually it will seem to work, but it can make your files dependant on the compiler used to compile the program reading the file, and details such as the CPU the program was running on - and you can''t rearrange the structure without breaking things.
January 23, 2001 10:16 PM
quote:
Original post by Ecco2000
typedef struct
{
char header[4]; // 4 bytes
short version; // 2 bytes
short flags; // 2 bytes
short compression; // 2 bytes
short modtime; // 2 bytes
short moddate; // 2 bytes
long crc; // 4 bytes
long compressedsize; // 4 bytes
long uncompressedsize; // 4 bytes
short filenamelength; // 2 bytes
short extrafieldlength; // 2 bytes
} xf_file_header;
could anyone tell me why sizeof(xf_file_header) returns 32 and not 30 like it is supposed to.
The two extra bytes are being inserted between fields moddate and crc. Every field of this structure is naturally aligned (ie, two-byte ints are aligned to addresses divisible by two, four-byte ints aligned to addr div by four, etc), except the crc field, which is off its natural alignment by two bytes. So the compiler will (properly) insert two bytes before the field.
Two easy ways to deal with this. One, use the #pragma mentioned earlier, which is easy yet highly unportable. Second, order your fields by decreasing order of size (all four-byte fields first, then two-byte fields, etc). The latter is much more portable, only slightly more time consuming to do. Disadvantage, however, is sometimes readability (and occassionally can''t be completely reordered if dealing with C++ constructors).
January 24, 2001 04:22 AM
You should cange alignment only if you really need it.
It''s safer to do it in this way:
It''s safer to do it in this way:
|
January 24, 2001 04:22 AM
You should cange alignment only if you really need it.
It''s safer to do it in this way:
It''s safer to do it in this way:
|
All of the things mentioned above are pretty much correct. You really should try to move the variables in your structure around first before playing around with #pragma pack(), especially because (as mentioned before) you can get huge penalties if your data isn''t aligned properly (I once wrote a Game of Life simulator; just by making sure the data was aligned properly I got a speed increase of over 300%!).
The only thing where you''ll really need to use #pragma pack() is when you''re accessing files or sending data across the network, because the alignment settings will be different on different systems. It can''t hurt to rearrange the variables first though.
And of course, _always_ use sizeof() instead of a hardcoded value. This should be pretty obvious, unless you enjoy hunting the bugs after you change the structure...
cu,
Prefect
The only thing where you''ll really need to use #pragma pack() is when you''re accessing files or sending data across the network, because the alignment settings will be different on different systems. It can''t hurt to rearrange the variables first though.
And of course, _always_ use sizeof() instead of a hardcoded value. This should be pretty obvious, unless you enjoy hunting the bugs after you change the structure...
cu,
Prefect
Widelands - laid back, free software strategy
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement