PDA

View Full Version : failing to achieve desired size of a BitField structure



nass
13th February 2007, 11:43
hello everyone,
i read somewhere that it is possible to define a BitFields structure
so i set out to:


struct IC_X
{
unsigned short int dump:2;
unsigned short int ic1:10;
unsigned short int ic2:10;
unsigned short int ic3:10;
};
struct EVS
{
unsigned short int dump:2;
unsigned short int v:10;
unsigned short int p:10;
unsigned short int q:10;
};
struct SE_P
{
unsigned short int dump:1;
unsigned short int c1s:1;
unsigned short int c2s:1;
unsigned short int c3s:1;
unsigned short int c1e:1;
unsigned short int c2e:1;
unsigned short int c3e:1;
unsigned short int rC:1;
};
struct ALS
{
unsigned short int dump:5;
unsigned short int al1:1;
unsigned short int al3:1;
unsigned short int al4:1;
};
then


struct LogEntry
{
IC_X icx;
EVS evs;
SE_P sep;
ALS als;
FileTime TimeStamp;
};

FileTime is just a typedef for an unsigned long.
dump fields are NOT used.

so basically i wanted to pack 3, 10-bit numbers in IC_X (and leave the 2 MSB bits unused), then another 3 10-bit nums in EVS, then 7 bools in SE_P, and another 3 bools in ALS.
finally pack them all together (along with an unsigned long timeStamp) to a 14byte long structure.
with this structure though i get a sizeof(LogEntry)=20 in execution...

what am i missing?
thank you for your help
nass

camel
13th February 2007, 12:01
As far as I know, gcc will align structs and certain types on word boundaries. (For example to speed up access)

To avoid that read about the Type Attribute "Pack" (http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes.html)

Hope it helps :-)

nass
13th February 2007, 12:06
hm perhpas i should mention
that i us g++... not gcc... i hope that doesn't mees everything up... eh??
please tell me it doesn't ...!:(

camel
13th February 2007, 12:07
I personally think that it shouldn't matter, as gcc and g++ are very much related :-)

If you go up one level in the documentation you will find the following nugget:

These extensions are available in C and Objective-C. Most of them are also available in C++.

I would suggest: just try it out ;-)

nass
13th February 2007, 12:39
so i added in my structures:

29: struct IC_X __attribute__ ((__packed__))
30: {
31: unsigned short int dump:2;
32: unsigned short int ic1:10;
33: unsigned short int ic2:10;
34: unsigned short int ic3:10;
35: };

but it didnt compile. it would give me the errors:

logger.h:30: error: syntax error before `{' token
logger.h:32: error: syntax error before `:' token
logger.h:33: error: syntax error before `:' token
logger.h:34: error: syntax error before `:' token

so i surfed around some more for bitfields and c++ and in
http://msdn2.microsoft.com/en-us/library/ms858673.aspx

i found that i shouldn't be declaring types.. now IC_X looks like:
struct IC_X
{
unsigned dump:2;
unsigned ic1:10;
unsigned ic2:10;
unsigned ic3:10;
};

and so do all the rest. it compiles and i get sizeof(IC_X)=4.. so OK.

BUT

the structures

struct SE_P
{
unsigned dump:1;
unsigned c1s:1;
unsigned c2s:1;
unsigned c3s:1;
unsigned c1e:1;
unsigned c2e:1;
unsigned c3e:1;
unsigned rC:1;
};
struct ALS
{
unsigned dump:5;
unsigned al1:1;
unsigned al3:1;
unsigned al4:1;
};

which i would like them to be of size 1byte... are not, they also return sizeof(ALS)=4...

so i'm still looking on how to fix these 2.
smth like __attribute__ ((__packed__)) would work nicely here... but it seems g++ has a problem with it..
any other pointers you might have are welcome
nass

jacek
13th February 2007, 13:04
Try:
struct IC_X
{
unsigned short int dump:2;
unsigned short int ic1:10;
unsigned short int ic2:10;
unsigned short int ic3:10;
} __attribute__ ((__packed__));

nass
13th February 2007, 13:22
finally what did the trick to get sizeof(LogEntry)=14... :


struct LogEntry
{
unsigned ic1:10;
unsigned ic2:10;
unsigned ic3:10;
unsigned dm1:2;//no name is for padding. :0 is for the next field to start in a new storage unit

unsigned v:10;
unsigned p:10;
unsigned q:10;
unsigned dm2:2;

unsigned c1s:1;
unsigned c2s:1;
unsigned c3s:1;
unsigned c1e:1;
unsigned c2e:1;
unsigned c3e:1;
unsigned rC:1;
unsigned dm3:1;

unsigned al1:1;
unsigned al3:1;
unsigned al4:1;
unsigned dm4:5;

unsigned long TimeStamp;
} __attribute__ ((__packed__));

without the packed attribute i'd get a sizeof 16.
'dm*' are the dummy bits.

Thank you both for your help!
nass

nass
13th February 2007, 14:13
any idea if timestamp will be LSB or MSB in intel processor when i will compile this structure???:confused:

camel
13th February 2007, 14:29
The most cross-platform thing to do would be to check
Q_BYTE_ORDER being equal to Q_BIG_ENDIAN or Q_LITTLE_ENDIAN and do the appropriate thing. Such as:


#if Q_BYTE_ORDER == Q_BIG_ENDIAN
//Do something
#else
//Do something else
#endif


But if you only need intel, you should be safe to only consider little-endian