Bitfield structs that are not padded to the size of an int?

D

Davide Bruzzone

Greetings all...

I need to create a number of bitfield structs whose contents are
smaller than the size of an int. For example:

typedef struct foo FOO;

struct foo {
unsigned char fieldOne: 2, fieldTwo: 6;
};

I'd like this struct to take up no more than 8 bits, however, when I
call sizeof(FOO), the function returns 4 bytes (which is the size of
an int on the platform on which I'm compiling my code).

Now I know that according to the ANSI C standard, this is normal (i.e.
Bitfield structs are padded to the size of an int). What I'm having
trouble finding more/clearer information about is:

- Whether its possible to force the compiler to bend/break this rule,
and to create non-padded bitfield structs that take us, say, one byte
or two (BTW, I'm using GCC 2.95.1).
- If this is possible, how I go about doing it (i.e. What command-line
options I need to use, and what, if anything, I need to add to my
code).

Any suggestions, or pointers to the appropriate information would be
greatly appreciated.

Cheers...

Dave Bruzzone
 
D

Derk Gwen

# - Whether its possible to force the compiler to bend/break this rule,
# and to create non-padded bitfield structs that take us, say, one byte
# or two (BTW, I'm using GCC 2.95.1).

Or just use a byte, and do the field extractions and insertions yourself.
 
D

Davide Bruzzone

Derk Gwen said:
# - Whether its possible to force the compiler to bend/break this rule,
# and to create non-padded bitfield structs that take us, say, one byte
# or two (BTW, I'm using GCC 2.95.1).

Or just use a byte, and do the field extractions and insertions yourself.

Having thought further about the problem, I suppose that a better way
to have asked the question would probably have been:

I have a stream of bytes (or characters) from which I need to extract
information. Since the individual bytes within the stream may use "bit
fields" within those bytes to represent specific pieces of
information, I thought that I might create a struct into which I could
copy the stream of bytes. I don't know whether this is possible, and
if it is, whether or not this is a dumb way to do it.

So, I suppose that my question should have been:

Given a stream of bytes:

Byte
0 1 etc.
Bit
1234567812345678...

aabbccccdddddddd...

Where aa represents a specific piece of information, bb represents
another piece of information, cccc yet another piece of information,
and so on...

What is the best way to read this stream of bytes and extract all
these pieces of information from it? Should I just read the stream
into a big buffer and use bit masks?

Thank you for your initial suggestion...

Cheers...

Dave Bruzzone
 
D

Davide Bruzzone

- If this is possible, how I go about doing it (i.e. What command-line
Try a gcc newsgroup since this is really a compiler question at this
point.

Doh! Thanks for the suggestion Mark...

Cheers...

Dave Bruzzone
 
E

Eric Sosman

Davide said:
Having thought further about the problem, I suppose that a better way
to have asked the question would probably have been:

I have a stream of bytes (or characters) from which I need to extract
information. Since the individual bytes within the stream may use "bit
fields" within those bytes to represent specific pieces of
information, I thought that I might create a struct into which I could
copy the stream of bytes. I don't know whether this is possible, and
if it is, whether or not this is a dumb way to do it.

Bit fields *look* like a way to do this, but as you've
discovered they're really not up to the job. (Similarly,
structs *look* like a way to match externally-defined data
formats, but they're not quite capable of it.)
So, I suppose that my question should have been:

Given a stream of bytes:

Byte
0 1 etc.
Bit
1234567812345678...

aabbccccdddddddd...

It is more usual to number the bits from 0 to 7 (or
from 0 to N; see below), from least- to most-significant.
That way, the number of each bit is the same as the power
of two that it represents, and this has mnemonic value.
Where aa represents a specific piece of information, bb represents
another piece of information, cccc yet another piece of information,
and so on...

What is the best way to read this stream of bytes and extract all
these pieces of information from it? Should I just read the stream
into a big buffer and use bit masks?

That's the most portable approach. Note that I wrote
"most," not "completely," because C doesn't require that a
byte be only 8 bits wide ... Most general purpose computers
today use 8-bit bytes, but machines with 32-bit bytes are
found in some arenas. Other widths are certainly possible
and have been used, but 9-bit bytes are today mostly a fading
memory.

Your job will be simplified if you happen to know that
the fields of interest are always entirely contained within
single bytes. Assuming an 8-bit byte, your example could be
decoded this way:

unsigned char b0, b1;
int aa = b0 >> 6;
int bb = (b0 >> 4) & 0x3;
int cccc = b0 & 0xF;
int dddddddd = b1;

If fields sprawl across byte boundaries things get messier,
but not irretrievably so. The approach is to extract the
sub-fields from different bytes and then to piece them together.
If in your example there were eight c's and four d's instead
of the other way around, it could be decoded thus:

unsigned char b0, b1;
int aa = b0 >> 6;
int bb = (b0 >> 4) & 0x3;
int cccccccc = ((b0 & 0xF) << 4) | (b1 >> 4);
int dddd = b1 & 0xF;
 
M

Martin Ambuhl

Davide said:
Greetings all...

I need to create a number of bitfield structs whose contents are
smaller than the size of an int. For example:

typedef struct foo FOO;

struct foo {
unsigned char fieldOne: 2, fieldTwo: 6;
};

I'd like this struct to take up no more than 8 bits, however, when I
call sizeof(FOO), the function returns 4 bytes (which is the size of
an int on the platform on which I'm compiling my code).

Then don't use bitfields. If CHAR_BIT==8 on your machine, just use
unsigned chars and normal bitwise operators. If CHAR_BIT > 8 on your
machine, then you can't (in C) do what you want.
 
T

The real OS2 guy

Having thought further about the problem, I suppose that a better way
to have asked the question would probably have been:

I have a stream of bytes (or characters) from which I need to extract
information. Since the individual bytes within the stream may use "bit
fields" within those bytes to represent specific pieces of
information, I thought that I might create a struct into which I could
copy the stream of bytes. I don't know whether this is possible, and
if it is, whether or not this is a dumb way to do it.

So, I suppose that my question should have been:

Given a stream of bytes:

Byte
0 1 etc.
Bit
1234567812345678...

aabbccccdddddddd...

Where aa represents a specific piece of information, bb represents
another piece of information, cccc yet another piece of information,
and so on...

What is the best way to read this stream of bytes and extract all
these pieces of information from it? Should I just read the stream
into a big buffer and use bit masks?

Thank you for your initial suggestion...

You've 2 choices:
1. implementation defined:

union c {
struct bits {
unsigned char a :2;
unsigned char b :2;
unsigned char c ....
} bits;
char chr;
}uc;

copy one char in c.char and read the bits. It's critical because
you can't port the program between different implementations (may
be not even between different versions of the same implementation).

uc.chr = readed_char;

2. standard compilant:

Fiddle out the bits of each char by hand and set them.

c = (readed_char & 0xc0) >> NUMBER_OF_BIT_SHIFT_a;
bits.a = c;
c = readed_char & 0x30 ..........

work with the bits by name....

write_char = (bits.a & 0x03) << NUMBER_OF_BIT_SHIFT_a;
write_char |= ......

If you needs a compact form you will be implementation defined because
you needs an implementation defined #pragma to push away the natural
alignment the implementation uses to pack data members of a
struct/union to its minimal size:

#pragma align(1)
union c c_arr[4711];
#pragma align()

In that case you can simply use the array directly to read/write the
stream. But you has to recheck your solution when the version of your
implementation changes.

When you needs to be standard conform you have no chance to build an
array in packed form.

--
Tschau/Bye

Herbert Rosenau
http://www.pc-rosenau.de eComStation Reseller in Germany
eCS 1.1 german is in beta testing
 
T

The real OS2 guy

Don't use bitfields.

Why not? The only you needs is an clearly defined interface to
(un)serialise the bitstream. No macro can make the code really
readable, but a bit structure makes it. You needs the macros you
describes in the serialiser functions, but you can access the bits in
the whole application by theyr names.

Use an unsigned char and masks. You can
make the access clearer with a few macros:

#define getFLDone(x) (x & 0x3)
#define getFLDtwo(x) ((x & 0xfc) >> 2)

#define setFLDone(x, val) ((x & 0xfc) | (val & 0x3))
#define setFLDtwo(x, val) ((x & 0x3) | (val << 2))

all untested. Now I suspect you can write:

unsigned char storage, another;
...
whatever = getFLDone(storage);
another = setFLDtwo(storage, whatever);

Make a clean design of the app and you non't need to fiddle around
with binary operators and shift operations in the app, because the
compiler can do this under cover for you. The only you needs is an
interface to the external storage that produces both, bytes to
bitfields and back. Even as the interface itself is only
implementation defined your app can be standard compilant.

In every bigger project you have a little part that is implementation
defined. Now you've a bit more to make the bitfields independant, but
that it's.

--
Tschau/Bye

Herbert Rosenau
http://www.pc-rosenau.de eComStation Reseller in Germany
eCS 1.1 german is in beta testing
 
D

Davide Bruzzone

To all who have responded...

Thnks again for all your responses. They've all be very useful and enlightening.

Cheers...

Dave
 
A

Adam S. Roan

You can only use bit fields on words. And manipulate words using bit-fields.

--bloodeu
 

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,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top