# Macro to Optimize Space for Embedded Array

Discussion in 'C Programming' started by Michael B Allen, Jul 31, 2005.

1. ### Michael B AllenGuest

Let's say I have a stucture with a flexible array at the end:

struct foo {
short s;
char bits[1];
};

I would like to embed this in other structures like:

#define TAILBITS 500

struct bar {
int i;
struct foo f;
char tail[TAILSIZE(500)];
};

My question is, can someone define a macro TAILSIZE that evaluates to
an optimal value for holding the specified number of bits in foo->bits?

Like a good poster I have tried this beforehand and came up with the

#define PAD (sizeof(struct foo) - offsetof(struct foo, bits))
#define BYTES4BITS(nbits) (((nbits) + 1) / 8)
#define TAILSIZE(nbits) ((PAD + 1) > BYTES4BITS(nbits) ? 1 : BYTES4BITS(nbits) - PAD)

At first glance this appears to work but is it legit?

Thanks,
Mike

Michael B Allen, Jul 31, 2005

2. ### Michael MairGuest

Michael B Allen wrote:
> Let's say I have a stucture with a flexible array at the end:
>
> struct foo {
> short s;
> char bits[1];
> };
>
> I would like to embed this in other structures like:
>
> #define TAILBITS 500
>
> struct bar {
> int i;
> struct foo f;
> char tail[TAILSIZE(500)];
> };
>
> My question is, can someone define a macro TAILSIZE that evaluates to
> an optimal value for holding the specified number of bits in foo->bits?
>
> Like a good poster I have tried this beforehand and came up with the
>
> #define PAD (sizeof(struct foo) - offsetof(struct foo, bits))
> #define BYTES4BITS(nbits) (((nbits) + 1) / 8)
> #define TAILSIZE(nbits) ((PAD + 1) > BYTES4BITS(nbits) ? 1 : BYTES4BITS(nbits) - PAD)
>
> At first glance this appears to work but is it legit?

PAD certainly is okay, as is TAILSIZE (even though I might have
formulated it slightly differently).
If BYTES4BITS is supposed to return the number of bytes necessary
to hold a certain number of bits, you have to try again:
Say you want to hold 9 Bits, then BYTES4BITS tells you one Byte
was quite enough. I.e. you need
#define BYTES4BITS(nbits) (((nbits) + 7) / 8)
or, better yet
#define BYTES4BITS(nbits) (((nbits) + (CHAR_BIT-1)) / CHAR_BIT)

Note that there is not guarantee whatsoever that the struct hack
works in C89 even though it seems to do so (and probably even on
early versions of the DS9000).

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.

Michael Mair, Aug 1, 2005

3. ### Michael B AllenGuest

On Mon, 01 Aug 2005 08:36:14 +0200, Michael Mair wrote:

>> #define BYTES4BITS(nbits) (((nbits) + 1) / 8)
>>

> If BYTES4BITS is supposed to return the number of bytes necessary
> to hold a certain number of bits, you have to try again:
> Say you want to hold 9 Bits, then BYTES4BITS tells you one Byte
> was quite enough. I.e. you need
> #define BYTES4BITS(nbits) (((nbits) + 7) / 8)
> or, better yet
> #define BYTES4BITS(nbits) (((nbits) + (CHAR_BIT-1)) / CHAR_BIT)

Ah, right. Thanks.

Actually the CHAR_BIT thing confuses me a little. I thought char was
guaranteed to be 8 bits? Are there some little 7 bit micro controllers
that can only hold 7 bits per char?

Thanks,
Mike

Michael B Allen, Aug 1, 2005
4. ### Ben PfaffGuest

Michael B Allen <> writes:

> Actually the CHAR_BIT thing confuses me a little. I thought char was
> guaranteed to be 8 bits? Are there some little 7 bit micro controllers
> that can only hold 7 bits per char?

char is at least 8 bits. It may be larger.
--
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield

Ben Pfaff, Aug 1, 2005
5. ### Tim RentschGuest

Michael B Allen <> writes:

> Let's say I have a stucture with a flexible array at the end:
>
> struct foo {
> short s;
> char bits[1];
> };
>
> I would like to embed this in other structures like:
>
> #define TAILBITS 500
>
> struct bar {
> int i;
> struct foo f;
> char tail[TAILSIZE(500)];
> };
>
> My question is, can someone define a macro TAILSIZE that evaluates to
> an optimal value for holding the specified number of bits in foo->bits?
>
> [...snip proposed definition...]

(Slight aside: probably better to use 'unsigned char' rather than
'char' for the bits, since with 'unsigned char' all values are
guaranteed to be available.)

In response to the question -- how about finessing the problem

#define BITMAP_STRUCT(n) \
struct { \
short s; \
unsigned char bits[ BYTES_FOR_BITS(n) ]; \
}

#define BYTES_FOR_BITS(n) ( ((n) + (CHAR_BIT-1)) / CHAR_BIT)

...

struct bar {
int i;
BITMAP_STRUCT( 500 ) f;
};

Unless there is a need to deal with 'struct foo' outside
the context of the other structs where they are embedded,
this approach seems to avoid all the difficulties.

Tim Rentsch, Aug 3, 2005