Archived

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

executor_2k2

size of struct problem

Recommended Posts

executor_2k2    122
I have a struct defined as follows: struct pos_t { unsigned long framenum; unsigned short accel; float pos_x, pos_y, pos_z; }; I did a "sizeof(pos_t)" and got 20 bytes. Shouldnt it be 18? Shorts are 2, floats are 4, longs are 4, right? Please correct me if Im wrong. Im writing in C++ on msvc++ 6.0. Thanks.

Share this post


Link to post
Share on other sites
Mr_Burns    122
It depends on your structure alignment. If you''re using a 32 bit compiler, as you probably are, I think the default alignment is 8 bytes or 4 bytes. This is because 32 bit processors prefer handling data in 32 bit chunks (4 bytes), so the compiler automatically aligns the structs to multiples or 4 or 8 bytes. If you change the struct alignment to 1 or 2 bytes, you should get 18, but this will result in worse performance.

Share this post


Link to post
Share on other sites
fallenang3l    144
Structure members don''t have to be stored consecutively in memory. Different systems can only allocate data on certain memory boundaries like half-word, word, or dword. Or in other words, the size of data items of a particular type is machine dependent, and because storage alignment considerations are machine dependent, so is the representation of the structure, too. Take this, for example:
struct s
{
double d1;
bool b1;
};

Theoretically, it should take up only 9 bytes in VC++ 7, but it takes up 16 bytes due to restrictions stated above.

Sometimes you can cut down the size of a structure significanly by simply rearranging its members so try different combinations if your struct seems bloated. Rearraning doesn''t always work, nevertheless it''s worth a shot.

Share this post


Link to post
Share on other sites
a person    118
you can modify padding, look at your project settings (if using VC++). there are also pargama commands you can use to modify it on a per struct basis. see your compiler manual, and search the net for further info.

useful for structs that you may use to read from files with, but NOT for general stuff as it will very likly slow memory access.

Share this post


Link to post
Share on other sites
Well, it''s better to just ensure the data members are evenly divisible by 32 bits. In this example, there''s no reason for accel to be a short because that only saves you 2 bytes (even with many instances of these, that''s insignificant) and it slows performance.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
executor_2k2    122
Well, the struct is defined by the .3ds format, so i cant do too much about the short. The struct defined by the .3ds format is 18 bytes which is not evenly divisible by 8(default packing). If I just set packing to 1 with "#pragma pack 1" will i be able to create a struct that's the same size as the one defined in the .3ds specification? Also, how do I set packing back to 8 after I make my 3ds structs? Thanks.

[edited by - executor_2k2 on May 4, 2002 1:42:41 AM]

Share this post


Link to post
Share on other sites
borkman    122
OK, I have an idea. If you really want the
data in memory to be tightly packed
(meanin no padding), I have a neat trick.
You can define a block of 18 bytes (characters).
Then assign references to specific locations in that
block of memory. Here's an example:


    

#include <iostream.h>

class pos_t{
public:
pos_t();
char data[18];


unsigned long& framenum;
unsigned short& accel;
float& pos_x;
float& pos_y;
float& pos_z;
};

pos_t::pos_t():
framenum(*((unsigned long*)data)), //bytes 0 - 3

accel(*((unsigned short*)(data + 4))), //bytes 4 - 5

pos_x(*((float*)(data + 6))), //bytes 6 - 9

pos_y(*((float*)(data + 10))), //bytes 10 - 13

pos_z(*((float*)(data + 14))) //bytes 14 - 17

{
cout << "this = " << this << endl;
cout << (&framenum) << endl;
cout << (&accel) << endl;
cout << (&pos_x) << endl;
cout << (&pos_y) << endl;
cout << (&pos_z) << endl;
}

int main (){
pos_t p;
cout << "sizeof(pos_t) = " << sizeof(pos_t) << endl;
return 0;
}



If you run the program, you might notice that the size of the
class itself is 40 bytes. That's probably due (at least in part)
to the underlying implementation of references by using pointers.
However, the actual data you're interested in is tightly packed
and starts at pos_t::data.



Steven Borkman
Home Page: http://www.borkman.mygamesite.net
Video Game Page: http://www.dev.mygamesite.net

[edited by - borkman on May 4, 2002 2:42:20 AM]

Share this post


Link to post
Share on other sites
poozer    122
I don't if this applies to your platform/compiler, but on my system:

1. Every variable/member is aligned on a boundary equal to its size. So a two-byte short is aligned on a two-byte boundary. A four-byte int is aligned on a four-byte boundary...

2. A struct takes the alignment of the member with the largest alignment. So if the struct is full of two-byte shorts, it will be aligned on a two-byte boundary. If the struct contains a two-byte short and a four-byte int, the struct will be aligned on a four-byte boundary. The rule is recursive and applies to structs nested inside of each other...

[edited by - poozer on May 4, 2002 4:09:32 AM]

Share this post


Link to post
Share on other sites
DrPizza    160
quote:
Original post by poozer
I don't if this applies to your platform/compiler, but on my system:

1. Every variable/member is aligned on a boundary equal to its size. So a two-byte short is aligned on a two-byte boundary. A four-byte int is aligned on a four-byte boundary...


What system is that?

Certainly not anything in common usage.

The only computer platform in common usage -- x86 -- permits unaligned access of all types, (except for the SIMD data types), and will, even with reasonable efforts by the compiler, still occasionally require unaligned data access. There's a particular issue with the 64 and 80-bit floating point types, as such variables, when created on the stack; the stack is normally (always?) only 4-byte aligned; either special fix-up code needs to be injected to align such floating point types properly, or they are just left unaligned.



[edited by - DrPizza on May 4, 2002 6:12:23 AM]

Share this post


Link to post
Share on other sites