Macro to Optimize Space for Embedded Array

M

Michael B Allen

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
following that takes advantage of any padding in the structure:

#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
 
M

Michael Mair

Michael said:
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
following that takes advantage of any padding in the structure:

#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
 
M

Michael B Allen

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
 
B

Ben Pfaff

Michael B Allen said:
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.
 
T

Tim Rentsch

Michael B Allen said:
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
instead?

#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.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top