Принудительное выравнивание битового поля C с использованием объединения - PullRequest
2 голосов
/ 13 января 2012

Мне было интересно, возможно ли принудительное выравнивание битового поля в C. Используя переменные в коде ниже, я знаю, что запись в _align_bytes , а затем чтение из битов не определена(и наоборот), потому что это зависит от реализации.Является ли приведенный ниже код допустимым методом «убеждения» битов быть сохраненными непрерывно в чем-то, что имеет размер беззнакового short?Я считаю, что (за исключением каких-либо проблем с порядком байтов) этот код верен ... но битовые поля и объединения - это две темы на Си, с которыми я менее всего знаком.

Я занимаюсь проектом микроконтроллера низкого уровня и хотел быпростой метод чтения битов конфигурации без тонны битовой маскировки.Спасибо за любые советы и предложения.

Сэм

PS Пожалуйста, не обращайте внимания на любые предположения, которые я делаю относительно порядка байтов, так как этот проект, над которым я работаю, очень низкого уровня и не предназначен для переноса на другие устройства /платформы.

#include <stdio.h>
#include <assert.h>

typedef union packet {
    struct {
        unsigned int bit0  : 1;
        unsigned int bit1  : 1;
        unsigned int bit2  : 1;
        unsigned int bit3  : 1;
        unsigned int bit4  : 1;
        unsigned int bit5  : 1;
        unsigned int bit6  : 1;
        unsigned int bit7  : 1;
        unsigned int bit8  : 1;
        unsigned int bit9  : 1;
        unsigned int bit10 : 1;
        unsigned int bit11 : 1;
        unsigned int bit12 : 1;
        unsigned int bit13 : 1;
        unsigned int bit14 : 1;
        unsigned int bit15 : 1;
    } bits;

    unsigned short _align_bytes;
} packet_t;

int main(int argc, char *argv[]) {

    assert(sizeof(unsigned short) == 2);

    unsigned short data = 0xA05F;
    packet_t *p = (packet_t *)&data;

    printf("%u", p->bits.bit15);
    printf("%u", p->bits.bit14);
    printf("%u", p->bits.bit13);
    printf("%u", p->bits.bit12);
    printf("%u", p->bits.bit11);
    printf("%u", p->bits.bit10);
    printf("%u", p->bits.bit9);
    printf("%u", p->bits.bit8);
    printf("%u", p->bits.bit7);
    printf("%u", p->bits.bit6);
    printf("%u", p->bits.bit5);
    printf("%u", p->bits.bit4);
    printf("%u", p->bits.bit3);
    printf("%u", p->bits.bit2);
    printf("%u", p->bits.bit1);
    printf("%u", p->bits.bit0);

    return 0;
}

Ответы [ 2 ]

3 голосов
/ 13 января 2012

Это обычный шаблон, и, насколько я знаю, ответ - да: битовые поля будут смежными и занимают ту же память, что и поле _align_bytes. В этом весь смысл союза, верно? Разные взгляды на одну и ту же память.

Я не уверен, что вы подразумеваете под "записью в _align_bytes, а затем чтением из битов не определено". Единственная проблема, которую я вижу, это endianess: бит 0 может быть lsb или msb _align_bytes. Если вы не хотите, чтобы он был переносимым, вам просто нужно сделать быстрый тест, чтобы выяснить, какой он, и вы должны быть настроены.

0 голосов
/ 13 января 2012

Я не уверен, но не нарушит ли это строгие правила алиасинга , потому что два указателя разных типов указывают на одну и ту же область памяти?В C89 и C99 вы не гарантированно вернете что-либо правильно.

Возможно, вы захотите проверить это, и при необходимости используйте -fno-strict-aliasing или что-то подобное для вашего компилятора, так что он отключает строгие псевдонимы, которые могут вызвать проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...