Suppose I have structure I'm using to model various packet formats:
#define MaxPacket 20
typedef struct {
u8 packetLength;
union {
u8 bytes[MaxPacket];
struct {
u16 field1;
u16 field2;
u16 field3;
} format1;
struct {
double value1;
double value2;
} format2;
};
} Packet;
I can expect that sizeof(Packet)
will be 21
. But is there any way to do something like:
sizeof(Packet.format2)
? I've tried that, but the compiler is not happy. Obviously, I could pull the format1
out as a separate typedef and then I could sizeof(format1)
. But I'm curious if I have to through all of that. I like the hierarchical composition of the formats. This is with gcc on an 8bit processor.
I'm equally interested if there's a way to use the nested type. IF I have to do a lot of
aPacketPointer->format2.value1; // not so onerous, but if the nesting gets deeper...
Then sometimes it would be nice to do:
Packet.format2 *formatPtr = &aPacketPointer->format2;
formatPtr->value2; // etc
Again, refactoring into a bunch of preceding typedefs would solve this problem, but then I lose the nice namespacing effect of the nested dotted references.
For something that will work even in C90, you can use a macro modeled on your toolchain's offsetof()
macro:
#define sizeof_field(s,m) (sizeof((((s*)0)->m)))
Adjust it accordingly if your toolchain's offsetof()
macro isn't based on casting 0
to a pointer to the structure's type.
When I use it like so:
std::cout << sizeof_field(Packet,format1) << std::endl;
std::cout << sizeof_field(Packet,format2) << std::endl;
I get the output:
6
16
For your second question, if you're willing to rely on GCC's typeof
extension you can create a similar macro for declaring pointers to your nested anonymous structs:
#define typeof_field(s,m) typeof(((s*)0)->m)
...
typeof_field(Packet,format2)* f2 = &foo.format2;
To be honest, I find that construct pretty ugly, but it might still be better than other options you have available.
GCC documents that the "operand of typeof is evaluated for its side effects if and only if it is an expression of variably modified type or the name of such a type", so the apparent null pointer deference should not result in undefined behavior when a variable length array is not involved.
Using C11 or C99, create a dummy compound literal and seek its size.
printf("%zu\n", sizeof( ((Packet){ 0, { "" }}).format2 ));
Output
16
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With