使用并集强制对齐C位域

时间:2012-01-13 17:01:43

标签: c struct bit-fields memory-alignment unions

我想知道是否有可能在C中强制对齐字段。使用下面代码中的变量我知道写入 _align_bytes 然后从位读取未定义(反之亦然)因为它是实现依赖的。下面的代码是否是一个有效的方法来“说服”连续存储在unsigned short大小的东西中?我相信(减去任何endian问题)这段代码是正确的......但是bitfields和union是我最不熟悉的两个C主题。

我正在做一个低级别的微控制器项目,并且想要一种简单的方法来读取配置位而无需大量的位屏蔽。感谢您的任何提示和建议。

萨姆

P.S。请忽略我对有关字节序的任何假设,因为我正在处理的这个项目非常低级,并不打算移植到其他设备/平台。

#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 个答案:

答案 0 :(得分:3)

这是一种常见的模式,据我所知,答案是肯定的:位字段将是连续的并占用与_align_bytes字段相同的内存。这就是工会的重点,对吗?查看同一记忆的不同方式。

我不确定你的意思是“写入_align_bytes然后从位读取是未定义的”。我看到的唯一问题是endianess:bit0可能是lsb或_align_bytes的msb。如果您不希望它是便携式的,那么您只需要进行快速测试以确定它是什么,并且您应该进行设置。

答案 1 :(得分:0)

我不确定,但这不会违反strict aliasing rules因为两个不同类型的指针指向同一个内存位置?在C89和C99中,您无法保证能够正确回归。

您可能需要对此进行测试,如果需要,请对编译器使用-fno-strict-aliasing或类似内容,以便禁用可能导致问题的严格别名。

相关问题