Размер двух структур одинаков, хотя в одной из них есть экземпляр структуры - PullRequest
0 голосов
/ 12 августа 2010
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));
}

В MessageWithParameters разве BaseMessage не принимает какой-то размер сам по себе?
Даже если он в стеке?
Я предполагаю, что компилятор превращает MessageWithParameters в нечто, похожее на FullMessage.
Я прав?

Ответы [ 3 ]

2 голосов
/ 12 августа 2010

Я полагаю, у вас есть проблема с отступами. База имеет 24-битный «остаток», в который могут поместиться 16-битные значения, добавленные в структуру параметров. Почему вы используете битовые поля? Они повсеместно осуждаются как Плохая Идея.

1 голос
/ 12 августа 2010

Как говорили другие, вы сталкиваетесь с заполнением ваших структур. Ничто в самом языке Си не может эффективно предотвратить это. Ваш компилятор может иметь некоторое расширение для pack вещей, например, gcc реализует это как attribute. Но для того, чтобы все было по-настоящему упаковано, вам нужно изменить порядок полей в порядке возрастания или убывания, чтобы промежутки выравнивания были как можно меньше.

Кроме того, использование битовых полей для таких структур, как правило, является плохой идеей. Если они у вас есть, используйте целочисленные типы C99 фиксированного размера, как показано ниже:

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

В этом случае, если ваш компилятор выровнен на 16 бит (редко в наши дни), вы можете просто потратить 8 дополнительных битов на BaseMessage.

1 голос
/ 12 августа 2010

Я предполагаю, что компилятор превращает MessageWithParameters в нечто, похожее на FullMessage.Я прав?

Никто не может сказать это.Компилятор волен решать.Стандарт гарантирует порядок членов и отсутствие заполнения перед самым первым членом (включая производные элементы).

...