ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
23 апреля
1080309 Топик полностью
yни (25.02.2021 09:38, просмотров: 347) ответил IBAH на еще вопрос знатокам си
Однобайтовое выравнивание возможно, но работать с ними опасно. К примеру, в modbus rtu заголовках используется однобайтовые поля, причём, размер некоторых заголовков нечётный. Не каждый может сказать как получить нечётный указатель на поле такого заголовка, поэтому обычно народ побайтно разбирает, как с массивом. У меня iar тоже никак не хотел отдать в runtime нечётный указатель, пока я ему специальное ключевое слово не вставил в тип указателя (__packed). Вот так создатели 

протокола сделали нехорошее. Считается плохим тоном делать однобайтовые поля без выравнивания их по размерам, кратным 2 или 4. Вы можете получить структуру с данными из внешних источников, при этом она может быть произвольно упакована и не привязана к правилам вашего компилятора. Так вот в памяти она может находиться и по нечётному адресу и поля её также могут иметь нечётные смещения. Чтобы не применять всякие ухищрения, как с modbus rtu заголовками - делайте их "жирнее". Кстати, offsetof(), указанный ранее, не работает с битовыми полями, насколько я помню, т.е. смещение можно получить только для полей разных типов в структуре. Рекомендую выравнивать по 2, а лучше по 4 байта, а резервные биты описывать явно. Сам пользуюсь этим для доступа к битовым полям периферийных регистров процессора:

// SDRAM Refresh Control Register (SDRCR).
typedef struct _SDRAM_REFRESH_CONTROL_REGISTER_FIELDS
{
    // Refresh rate. Defines the rate at which the attached SDRAM devices will be refreshed. The
    // value of this field may be calculated with the following equation:
    // RR = SDRAM frequency/SDRAM refresh rate
    // where SDRAM refresh rate is derived from the SDRAM data sheet.
    uint32_t RR: 16;

    uint32_t Reserved1: 7;

    // Self-refresh or Power-down select. This bit is only in effect when the LPMODEN bit is set to 1;
    // this bit is ignored when the LPMODEN bit is cleared to 0.
    // 0 - Self-refresh mode;
    // 1 - Power-down mode.
    uint32_t SR_PD: 1;

    uint32_t Reserved2: 6;

    // MCLK stop enable.
    // 0 - Disables MCLK stopping, MCLK may not be stopped;
    // 1 - Enables MCLK stopping, MCLK may be stopped. The LPMODEN bit must be set to 1 before
    // setting the MCLKSTOPEN bit to 1.
    uint32_t MCLKSTOPEN: 1;

    // Low-power mode enable.
    // 0 - Disable low-power mode;
    // 1 - Enable low-power mode. The state of bit SR_PD selects either self-refresh or power-down mode.
    uint32_t LPMODEN: 1;

} SDRAM_REFRESH_CONTROL_REGISTER_FIELDS, * PSDRAM_REFRESH_CONTROL_REGISTER_FIELDS;

typedef union
{
    uint32_t Value;
    SDRAM_REFRESH_CONTROL_REGISTER_FIELDS Fields;

} SDRAM_REFRESH_CONTROL_REGISTER, * PSDRAM_REFRESH_CONTROL_REGISTER;