tags:

views:

77

answers:

3
typedef struct BaseMessage
{
    int u32DeviceID : 32;
    int u32CoreID : 32;
    unsigned int u16Class : 16;
    unsigned int u8OpCode : 8;
    unsigned int u16CRC : 16;
} BaseMessage;

typedef struct MessageWithParameters
{
        BaseMessage base;
        int u8Param1 : 8;
        int u8Param2 : 8;
} MessageWithParameters;

typedef struct FullMessage
{
        int u32DeviceID : 32;
        int u32CoreID : 32;
        unsigned int u16Class : 16;
        unsigned int u8OpCode : 8;
        unsigned int u16CRC : 16;
        int u8Param1 : 8;
        int u8Param2 : 8;
} FullMessage;

int main()
{
        printf("%d", sizeof(MessageWithParameters));
        printf("%d", sizeof(FullMessage));
}

In MessageWithParameters doesn't the BaseMessage take some size by itself?
Even if it's on the stack?
I am guessing that the compiler turns MessageWithParameters to something that looks like FullMessage.
Am I correct?

+2  A: 

You have some padding issue, I would guess. The base has 24-bits "left over", into which the 16-bits added in the parameter struct could fit. Why are you using bitfields? They are universally reviled as A Bad Idea.

anon
Bad idea? NO. Rear? Yes. There is no "do always" or "do never". However, it was a bad idea to use them in a way like above.
adf88
What's wrong with bitfields?
DeadMG
I am using them to mimic the embedded system types. For instance Xuint32, Xuint16, Xuint8.@ad88: Why is it a bad idea?
the_drow
@DeadMG Non-portable, by definition. Can't take the address of them. Slow.
anon
They are no less portable than other parts of the language. And I'd be really worried for someone who needed a bit-field's address.. (can't say I haven't seen it, bit-field + offsetof = pure win)
Michael Foukarakis
@mfukar As regards portability, well Brian Kernighan for one would disagree with you (see The Practice Of Programming). And I would have thought taking the address of a structure field was quite a common operation.
anon
+1  A: 

I am guessing that the compiler turns MessageWithParameters to something that looks like FullMessage.
Am I correct?

Nobody can say that. Compiler is free to decide. The standard guarantees members order and no padding before the very first member (including derived members).

adf88
+1  A: 

As the others said you encounter padding of your structures. Nothing in the C language itself may effectively prevent this. Your compiler might have some extension to pack things, e.g gcc implements this as attribute. But to get things really packed, then, you'd need to reorder your fields in ascending or descending order, such that the alignement gaps get as small as possible.

Also, using bit fields for such structures is generally a bad idea. If you have them use the C99 fixed size integer types like in the following:

typedef struct BaseMessage
{
    int32_t u32DeviceID;
    int32_t u32CoreID;
    uint16_t u16Class;
    uint16_t u16CRC;
    uint8_t u8OpCode;
} BaseMessage;

In this case if your compiler alignes on 16 bits (rare these days) you could get away with just a waste of 8 other additional bits for BaseMessage.

Jens Gustedt
and what if I do __attribute__((packed)) on everything?
the_drow
This really depends on the alignement requirements of the target platform. You may relax these requirements by reordering your fields and by giving the `attribute`. But what results on your real-existing platform depends on a lot of constraints, in particular what addressing the cpu allows. In any case you will in most cases have a gap at the end, since I don't think that alignment on 8 bit boundaries does still exist.
Jens Gustedt
the_drow
@the_drow: I think the way to come close to this is as I described, and then verify the result on both ends. You could use the `offsetof` macro with every individual field to check this. Otherwise, if you really wanted to be sure to have minimal alignement *and* the same layout on both ends you have to allocate just a `char` array and to serialize your `struct`. But beware, this is only guaranteed to work for unsigned types, since at least in theory the representation of negative numbers may be different on different architectures. (Though they are two's complement almost everywhere.)
Jens Gustedt
@the_drow: I agree with Jens and here is a sample of how you can do it: typedef char rtest_1_[ (offsetof(MetaInfo, used)==36)?1:-1 ];
Zan Lynx