Archived

This topic is now archived and is closed to further replies.

#pragma pack() stuff

This topic is 5677 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I know it has been mentioned on an other forum already but I didn''t find a good answer on the question. Does anyone have a good explanation of the #pragma pack(n) directive? VC++ 6.0 only tells it can accept 1,2,4,8,16 as n. But I obviously don''t know what they mean. I''m using it as follows in my bmp structures and I know it is related to the byteorder: (as can be derived from the hex view of both, an original bmp and a program-made bmp)
  
#pragma pack(1)
struct BITMAPFILEHEADER		//header of a BMP-file

{
	short	bfType;		//Ident of a BMP-file ''BM''

	long	bfSize;		//size of our file

	short	bfRes1;		//something

	short	bfRes2;		//something else

	long	bfOffBits;	//the offset to the image bits

};
#pragma pack()
  
Could anyone explain what the values passed to pack() mean? =========================== UNKNOWN caused an invalid page fault in module unknown at 0000:bff80eb6 : win98 with multiple sclerose

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Variable alignment. The pack directive is for letting the compiler know how big a ''word'' it should be aligning the varibles on in your structure. Larger values mean extra space at the end of the struct, or possibililty space in between variables in the struct.

Packing the variables right improves performance, at the expense of portability. pack(1) is equivalent to aligning on byte boundries, which means no extra space at all. Structs that you expect to read and write from files (particuarly across multiple platforms) should be packed on byte boundaries.

Share this post


Link to post
Share on other sites
Thanks, I think I know what you''re talking about, there is still one question.
Why on earth, when I look at the hex view of the bitmap, c++ adds two zero bytes after the bfType. The bfType is a short and should be two bytes long in the file. Why does the compiler add two clean bytes. I''ve never had this problem when reading or writing files to/from structures, and now suddenly it occurs.
Of course it disappears when I use the #pragma pack(1) directive, but still: why does it occur when I don''t specify that any bytes should be added?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The compiler adds it so that it aligns on a certain boundary, x86 are 32-bit cpu''s and take a performance hit if they are accessing memory that is not aligned to 32-bit''s (I believe it''s 32-bit''s not sure though).

So essentially the compiler does this to optimize your program .

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by SwSh
Thanks, I think I know what you''re talking about, there is still one question.
Why on earth, when I look at the hex view of the bitmap, c++ adds two zero bytes after the bfType. The bfType is a short and should be two bytes long in the file. Why does the compiler add two clean bytes. I''ve never had this problem when reading or writing files to/from structures, and now suddenly it occurs.
Of course it disappears when I use the #pragma pack(1) directive, but still: why does it occur when I don''t specify that any bytes should be added?



The intel is a 32 bit processor, so by default it aligns variables every four bytes.

In this case you''ve got a two byte variable followed by a four byte variable. Access will be fastest if the end of the second variable comes four bytes after the end of the first variable so... the compiler inserts two extra bytes.\

The long and the short of it is that the default packing on an intel CPU is ''4.''

Share this post


Link to post
Share on other sites
To elaborate on AP''s post, consider what would happen if it didn''t try to align on a 4-byte boundary. This is based on a 32-bit processor that always retrieves data in 32-bit sections. ie: x86.

If you set it to byte alignment (pack 1), then everything after bfType would cross a 4-byte boundary. Any time that the CPU tried to access anything after bfType it would have to perform two separate retrievals from memory, and perhaps swap them. Thus, slower than 4-byte alignment.

It''d be even worse if that bfType was a char or a single byte.


  
[0000] bfType
[0001] bfSize
[0002] ...
[0003] ...
[0004] ...
[0005] bfRes1


Then when the cpu tried to retrieve bfSize, it would have to perform the same two retrievals (one from 0000, one from 0004), then do a few swaps to get everything into the proper order.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Just to cap off the discussion nicely, if you want your structures to work as well as is possibly with 1 byte packing, sort your variables. You''ll find that declaring the largest variables first will give you the best packing you''re gonna get without dummy space.

Share this post


Link to post
Share on other sites
Thanks a lot!
Now I think I''ve got it. So the byte alignment has actually not much to do with the sizeof(type). It''s just a matter of experimenting and nice sorting in structures to not waste proc cycles and code.
I''ll have to experiment some on that though.
tnx.

===========================
UNKNOWN caused an invalid page fault in module unknown at 0000:bff80eb6
: win98 with multiple sclerose

Share this post


Link to post
Share on other sites
the only reason i found to use a byte alignment was when loading file-headers into a header-object. if you don''t set the alignment to 1 for a header-class/struct, you''ll get wrong values while reading (because the fread writes into the ''empty'' memory. you''ll have to do put #pragma pack(1) / #pragma pack() around these classes/structs, or read each variable one by one

Share this post


Link to post
Share on other sites
Well, and it''s strange that I didn''t experience these problems in my earlier projects. Maybe just luck. But now I know how it works. tnx.

===========================
UNKNOWN caused an invalid page fault in module unknown at 0000:bff80eb6
: win98 with multiple sclerose

Share this post


Link to post
Share on other sites