sizeof and its wrath

Started by
16 comments, last by Abstraction 22 years, 2 months ago
So I had this struct and I was pretty dang sure it took up 14 bytes. Take a look...
  
typedef struct MS3D_HEADER
{
     char id[10];
     int  version;
};
  
Then I call sizof(MS3D_HEADER) and it says the thing is 20 bytes long. After a lot of recounting followed by breaking things and cursing I fumbled around the documentation of the sizeof function and read this (more or less)... sizeof will return the size of the object in bytes taking into account bytes added for memory padding. What!? Why are bytes added and what the heck is the padding for? Is it done by the system or the compiler? Does the padding come at the begining or the end? And what about this scenerio -
  
MS3D_HEADER header;
BYTE *prt;

ptr = (BYTE *)header;
ptr += 10;
  
Where does ptr point to. Is it at header.version, at some random byte spliced in there for memory allignment, or what? I am completely self taught and get blindsided by stuff like this all the time. So after you call me stupid and answer my questions (hopefully) could you suggest some books or other sources that would educate me. I''m getting tired of this sort of thing.
Advertisement
Well I THINK I read about padding once before and I THINK it works like this:
It likes everything in the structure to fit into 'cells' of memory which are the same size as the largest variable in the structure.
So, for instance, in your structure, the larges variable is that 10 byte string, but instead of appending the 4 byte int to the end of that 10 byte string, it allocates ANOTHER 10 bytes and sticks it in there.
BASICALLY it likes to increment the memory allocated to a structure by the largest element in that structure.
I not good at explaining...

PS: Consequently, if you really want to control this, I THINK you can use bit fields to restrict the size of the structure, but you need to look that up because I have no idea what I'm talking about =P

Edited by - Draxis on February 6, 2002 10:30:54 PM
Ok, so here is the deal.

Each processor has different alignment issues, if the data is aligned properly it will improve preformance, if it is not aligned properly it will decrease preformance.

Using a pack macro(look it up on MSDN) you can pack your data into the extra bits that are used to pad each variable, or you can change the alignment in the compiler options (if your using visual C++). What you don''t want to do is not have the data aligned as it will decrease your overall preformance.
A 3-second Google search came up with this, it should explain to you why your compiler pads structs.

If you want to change which boundary your compiler pads at, read your compiler's manual. If you're using MSVC, you can either use the /ZpX compiler switch (where X is the number of bytes to align to, 1 being no padding), or you can use the #pragma pack(push, X) directive and #pragma pack(pop). e.g:

    #pragma pack(push, 1) // changes byte alignment to 1struct myStruct {  int myInt;  long myLong;};#pragma pack(pop) // changes back to the default byte alignment    


Edited by - Spiral on February 6, 2002 10:38:53 PM
--------------------Go Stick Your Head In A Pig
Just to illustrate why your struct came out at 20 bytes:

      typedef struct MS3D_HEADER{     char id[10];    // Data size is 10, this will be padded to 16 bytes, so +6 extra     int  version;   // Data size is 4, this will have no padding                     // hence, 10 + 6 + 4 = 20};      


quote:Original post by Abstraction
Where does ptr point to. Is it at header.version, at some random byte spliced in there for memory allignment, or what?


I've actually never thought about this, but it should point to the padding byte just after id[9]. Why dont you try it?

[edit] - Just to clarify, the data sizes are the ones on my computer (ie char is 1 byte, int is 4 bytes). They may be different on other platforms. I use win2k.

Edited by - Spiral on February 6, 2002 10:51:47 PM
--------------------Go Stick Your Head In A Pig
quote:Original post by Draxis
Well I THINK I read about padding once before and I THINK it works like this:
It likes everything in the structure to fit into ''cells'' of memory which are the same size as the largest variable in the structure.
So, for instance, in your structure, the larges variable is that 10 byte string, but instead of appending the 4 byte int to the end of that 10 byte string, it allocates ANOTHER 10 bytes and sticks it in there.
BASICALLY it likes to increment the memory allocated to a structure by the largest element in that structure.
I not good at explaining...

PS: Consequently, if you really want to control this, I THINK you can use bit fields to restrict the size of the structure, but you need to look that up because I have no idea what I''m talking about =P


There was absolutely nothing correct in this post I''ve just explained your first point, and bit fields have nothing to do with alignment. They just allow you to specify the size/width of a variable.
--------------------Go Stick Your Head In A Pig
i think that it aligns to sizeof int, since the cpu works with ints best.

are u sure that 20 isnt a typo ? it should be 16, i think, since ints are 4 bytes long.

actually, i just tried it in mvc++, and its 16: what compiler are u using?
this is probably over cryptic. but anyway,
    #include <iostream>using namespace std;const max = 10; struct S{	char c[max];	int i;};void main(void){		cout << sizeof(S) << endl;	S s; 	for(int i = 0; i <max; i++)		s.c[i] = i;	s.i = 15;	char* ptr = (char*)&s		cout << (__int8)ptr[max - 1] << endl;	cout << *(int*)(&ptr[max] + sizeof(char) * ( 4 - max % 4));	cout << endl;	cout << (char*)&s.c - (char*)&s.i}    

i woiuldnt count on a compiler organizing the data to literally represent a struct, even though in this example, the pads are addes to before the int.

im pretty sure there is a way to turn off padding...

Edited by - evilcrap on February 6, 2002 11:03:47 PM
Thanks for the replies.

AP - you basically comfirmed my suspicsions, very reassuring.

Spiral - So it is my compiler and not some bizzar mechanism in memory. Thanks for the search. I have been doing the same thing, however, sometimes real live typing(?) people shed light on the little detials and pitfalls that are hard to realize on your own. Anyway, #pragma pack(push, 1) and pack(pop) sounds like a good solution. I''ve seen that before and always wondered, I quess now I know. Thanks a bunch (all of you) for your most excellent help.

Just one more thing. If I use the solution above and take one of my objects out of aligment will preformance be poor just in sections dealing with instances of the object or will it throw the whole application out of alligment.

Oh, I do have MSVC 6.0 (Introductory Edition). It didn''t come with a manual just some book about MFC and a book on CD that teaches you how to program (tries to at least). Only basic (very basic) information is given about the compiler''s settings and interface. I''ll shutup now.

EvilCrap - It comes out 20 every time, I swear. I have MSVC++ 6.0. Once I started hearing "memory alignment" and padding I totally thought it should by 16 or by some stretch 24 but not 20. I''m thinking Spiral knows what he''s talking about though.
Wait a second... i could be wrong in my analysis of what would happen in your struct... i''ve just tried it out on my compiler (MSVC 6 pro) and EvilCrap is right, it comes out as size 16. With some playing i''ve discovered it inserts 2 padding bytes after the char id[10].

Obviously one of those differences between the Introductory/Standard edition and Pro compilers, i suppose.

Anyway...

quote:
Just one more thing. If I use the solution above and take one of my objects out of aligment will preformance be poor just in sections dealing with instances of the object or will it throw the whole application out of alligment.


Wrapping whichever structs you want to change the alignment for with #pragma pack will just change the byte alignment for structs of that type... it will not effect the whole of your application. Using the /Zp switch will.
--------------------Go Stick Your Head In A Pig

This topic is closed to new replies.

Advertisement