is size of char 4 ???

Started by
14 comments, last by Zahlman 17 years, 1 month ago
hi, please have a look at this sample code using visual c++ 2005 express edition. typedef unsigned char byte ; struct Header { byte one ; int two ; }; void main() { cout << sizeof(Header) << endl ; } ok, the i would expect the result to print 5, BUT, I get 8 instead, how is this possible.
Advertisement
Your compiler is probably optimizing your struct by offsetting the int variable by 3 bytes.
this is creating some problems when using win TCP/IP and send/recv function.

do you suggest I forget about using bytes and use UINT everywhere.
or
try to disable that compiler optimization.
Padding and Alignment of Structure Members

C++ Structure: Why returns 'sizeof()' a bigger size than the members actually need?

IO:Cross Platform IO Tips
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by dynameat
this is creating some problems when using win TCP/IP and send/recv function.


It's generally a bad idea to send a struct directly over the wire. You can run into all sorts of trouble if you aren't careful. You would be much better served pulling the struct fields and manually packing them into a byte array in a fixed format. Aside from avoiding certain problems, it frees you up to more easily implement some form of packet compression later on down the road if you find that you need it. By separating the storage type from the transfer type of a value, you can do compression tricks like condensing several boolean values into a single 32-bit bit mask.
Some good links there from lessbread, but here is somethings to take into consideration.
Padding structures should be your last choice as it adds a speed penalty and is platform specific.
Correctly aligning your own structures costs nothing.
Not sure if bitfields incur a speed penalty?
You can develop a serialisation method that takes care of everything for you,see hplus' post in this thread

Finally use types which are guaranteed to be the same on all peers, what is the size of the variable "two"?
its already been said that you shouldn't send your struct through the network... but if you do write the entire struct at once, just be sure to read the entire struct at once (i.e. match your reads and writes with the same types).

e.g.

lets say you have send( void* data, uint size ) and receive( void* data, uint size );

you shouldn't do:
my_struct data;data.one = 128;data.two = 6552053;send( &data, sizeof(my_struct) );....my_struct data;receive( &data.one, sizeof(char) );receive( &data.two, sizeof(int) );

you should do: (this is better, but not portable)
my_struct data;send( &data, sizeof(my_struct) );....my_struct data;receive( &data, sizeof(my_struct) );

or better yet: (guaranteed to work)
my_struct data;send( &data.one, sizeof(char) );send( &data.two, sizeof(int) );....my_struct data;receive( &data.one, sizeof(char) );receive( &data.two, sizeof(int) );
What I'd do is have
struct foo{  data d1;  data d2;  data d3;  char* packetize()  {    //function that puts all members    //into proper packet form  }  void fromPacket(char* packet)  {    //take packet from form in packetize()    //and assign data to the members  }};

then you can just call packetize when sending and fromPacket when receiving ;0
For the record, sizeof(char) is always 1.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Quote:Original post by CmpDev
Some good links there from lessbread, but here is somethings to take into consideration.


OK, let's consider them.

Quote:Padding structures should be your last choice


Impossible; the compiler will run its structure-padding algorithm automatically (although *if* the members are put in the correct order *and if* the sizes all add up right, it might turn out that the total padding amounts to zero bytes).

Quote:as it adds a speed penalty


Incorrect. The compiler does it *specifically because*, among other things, it is expected to *improve* performance. You might lose out in *size*, though, if you just put in your data members in any old order rather than trying to pair up your shorts and arrange bytes in sets of four. But those numbers are platform specific; and anyway, there is nothing that can be done in the OP's example since there is only one char-sized member.

Quote:and is platform specific.


Well, yes, but...

Quote:Correctly aligning your own structures costs nothing.


The manner of correctly aligning structures technically is platform specific as well (nothing prevents me from creating hardware with a "native" integer size of 24 bits, for example, upon which the reference C++ compiler would naturally provide 24-bit ints, and your efforts to align things to 32-bit barriers would be all for naught). And certainly it *does* cost a fair bit - in terms of your development time.

(It is worth noting that the compiler is not allowed to rearrange your data members so that they will pack better.)

Quote:Not sure if bitfields incur a speed penalty?


Depends what you mean by "penalty"; i.e. what you are comparing to which.

Quote:You can develop a serialisation method that takes care of everything for you,see hplus' post in this thread


Of course.

Quote:Finally use types which are guaranteed to be the same on all peers, what is the size of the variable "two"?


A good thought. Unfortunately, the language itself doesn't really provide you with any, except for char (which is guaranteed to have a sizeof() == 1). In order to keep things in agreement, therefore, one normally relies on typedefs - either (again) platform-specific ones, or a wrapper such as provided by Boost (which, in turn, asks the preprocessor what the platform is and selects the appropriate platform-specific typedefs... I'm sure there's a more clever, template meta-programming way to make this work, but they don't seem to be doing it).

This topic is closed to new replies.

Advertisement