【问题标题】:Forcing alignment of C bitfield using a union使用联合强制对齐 C 位域
【发布时间】:2012-02-09 21:04:56
【问题描述】:

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

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

山姆

附:请忽略我对字节顺序所做的任何假设,因为我正在进行的这个项目非常低级,不打算移植到其他设备/平台。

#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;
}

【问题讨论】:

  • 您应该对bits_align_bits 使用相同的类型。如果您的 int 大小不同(例如 sizeof(int) == 4 和 sizeof(short) == 2)并且位域按您不期望的顺序排序,那么您的 bits 可能不会重叠 _align_bits。字节序和位域排序是不同的。
  • “实现依赖”不是“未定义”。而且由于您使用的是微控制器编译器,这种黑客行为很常见,我认为您很安全。因为,是的,这是强制位域对齐/填充的正常方式。

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


【解决方案1】:

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

我不确定“写入 _align_bytes 然后从位读取未定义”是什么意思。我看到的唯一问题是字节序:bit0 可能是 _align_bytes 的 lsb 或 msb。如果你不希望它是便携的,那么你只需要做一个快速测试来确定它是什么,你应该设置好。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-02
      • 2012-09-05
      • 2015-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      相关资源
      最近更新 更多