Tail space in struct within struct

M

Michael B Allen

Consider the following structures:

struct bar {
int i;
float f;
unsigned char tail[1];
};
struct foo {
struct bar b1;
unsigned char _b1tail[B1N];
struct bar b2;
unsigned char _b2tail[B2N];
};

Can I rely on the order of members such that _b1tail will occupy at
least B1N bytes between b1 and b2?:

&foo->b2 - &foo->b1 >= sizeof(struct bar) + BN

So I can use &foo->b2 as the effective end of _b1tail?

Thanks,
Mike
 
M

Malcolm

Michael B Allen said:
Consider the following structures:

struct bar {
int i;
float f;
unsigned char tail[1];
};
struct foo {
struct bar b1;
unsigned char _b1tail[B1N];
struct bar b2;
unsigned char _b2tail[B2N];
};

Can I rely on the order of members such that _b1tail will occupy at
least B1N bytes between b1 and b2?:

&foo->b2 - &foo->b1 >= sizeof(struct bar) + BN

So I can use &foo->b2 as the effective end of _b1tail?
Yes, but it is what Denis Ritchie calls an "unwarranted chumminess with the
implementation".
I think that the member array "tail" should be zero-sized, however, to
prevent the compiler inserting a trap at position two.
 
A

Arthur J. O'Dwyer

Michael B Allen said:
struct bar {
int i;
float f;
unsigned char tail[1];
};
struct foo {
struct bar b1;
unsigned char _b1tail[B1N];
struct bar b2;
unsigned char _b2tail[B2N];
};

Can I rely on the order of members such that _b1tail will occupy at
least B1N bytes between b1 and b2?:

&foo->b2 - &foo->b1 >= sizeof(struct bar) + BN

Of course you meant something more like

(char*)&foo->b2 - (char*)&foo->b1 >= sizeof(struct bar) + B1N

but following that correction, it's correct; you may assume that.
This is because all struct members come one after another in the order
they're defined in the struct definition.
Yes, but it is what Dennis Ritchie calls an "unwarranted chumminess with
the implementation".

Caveat: It depends what you mean by "use." For example, AFAIK it
invokes undefined behavior to write

((char*)&foo->b2)[-1] = 42; /* modify the "last" byte of |_b1tail| */

because the implementation might have put a padding and/or checksum byte
there, and wantonly changing padding bytes is a Bad Thing. (I could be
wrong about the Standard-mandated effect of changing padding bytes, but
it seems reasonable to me.)
I think that the member array "tail" should be zero-sized, however, to
prevent the compiler inserting a trap at position two.

Bad advice. Last I checked, zero-sized objects were not supported in C.
Maybe if Michael explains what he's really trying to do, a better (more
portable) solution will be reached.

HTH,
-Arthur
 
M

Michael B Allen

Yes, but it is what Dennis Ritchie calls an "unwarranted chumminess
with the implementation".

Caveat: It depends what you mean by "use." For example, AFAIK it
invokes undefined behavior to write

((char*)&foo->b2)[-1] = 42; /* modify the "last" byte of |_b1tail| */

Maybe if Michael explains what he's really trying to do, a better (more
portable) solution will be reached.

Ok. The tail members are bitmaps that are different sizes depending on
needs. I have a struct with several of these object/bitmap pairs that
I initialize with a function like:

int
bar_init(struct bar *b, void *blim, float f)
{
memset(b, 0, blim - (void *)b);
b->blim = blim;
if (something_init(&b->something, f) == -1) {
return -1;
}
b->tail[0] = 0x01; /* don't use bit 0 */
return 0;
}

So when I call this initializer I need to know the end of the tail so
that my bitset rountines know where to stop. Rather than try to compute
this point I reasoned that provided the order of members is maintained
that the member following the tail is and effective blim.

if (bar_init(&foo->b1, &foo->b2, 1.1) == -1 ||
bar_init(&foo->b2, &foo->b3, 2.2) == -1 ||
bar_init(&foo->b4, foo + 1, 3.3) == -1) {
return -1;
}

So based on what you've said I think I'm ok.

Thanks,
Mike
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top