failing to achieve desired size of a BitField structure

N

nass

hello everyone,
i read somewhere that it is possible to define a BitFields structure
so i set out to:

Code:
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
Code:
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
 
D

dasjotre

<snip>

You work on a 32 bit machine.

It is all due to alignment of primitive types.
In IC_X, the firs two members fit in one short,
next two can only fit in two shorts, and since
short alignment is 2, sizeof(IC_X) == 6.

EVS is the same.

SEP members fit in one short, hence
sizeof(SEP) == 2. same with ALS.

FileTime is long which is aligned on
word boundary hence sizeof(FileTime) = 4

It all adds up to 20.

make IC_X and EVS to use unsigned
int instead of short and SEP and ALS
to use char and then look-up struct alignment
directive for your compiler and set it to 1
(remember to reset it afterwards)
 
N

nass

thank you for the reply. in the end actually re-did the structure in
the following way:

struct LogEntry
{
unsigned ic1:10;
unsigned ic2:10;
unsigned ic3:10;
unsigned dm1:2;

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__));

now sizeof(logEntry) returns 14 as expected. the 'dm*' are dummy
unused variables.
Thank you for your help
nass
 
P

Pete Becker

nass said:
thank you for the reply. in the end actually re-did the structure in
the following way:

struct LogEntry
{
unsigned ic1:10;
unsigned ic2:10;
unsigned ic3:10;
unsigned dm1:2;

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__));

now sizeof(logEntry) returns 14 as expected. the 'dm*' are dummy
unused variables.

A more portable way of doing that is to specify a width of 0, which
tells the compiler to advance to the next allocation unit boundary.
Also, you don't need to give names to the ones that are used only for
padding. Of course, none of the details are guaranteed: you have to
adapt to the compiler you're using.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top