反转结构位域的顺序

时间:2021-04-18 18:15:00

标签: c binary

我试图在 C 中实现一个伪位数组,我在其中定义了一个具有 8 个 1 位成员的结构,然后将其内存地址转换为 unsigned char。这种方法确实有效,但它会翻转二进制数中的位顺序。例如。 127 会变成 254。我该如何撤消此操作?

struct bit_array {
    unsigned b8:1, b7:1, b6:1, b5:1, b4:1, b3:1, b2:1, b1:1;
};


unsigned char join(struct bit_array num) {
    return *(unsigned char*)#
}

int main() {
    struct bit_array test_bits = { 1, 1, 1, 1, 1, 1, 1, 1 };
    printf("%u", join(test_bits));
    return 0;
}

1 个答案:

答案 0 :(得分:1)

C 标准既不指定用于它们的任何存储单元中的位字段顺序,也不指定无符号整数中的位顺序,除非说它们是实现定义的并暗示位字段要么是高的-到低或从低到高(而不是混合)。

C 2018 6.7.2.1 说:

<块引用>

单元内位域的分配顺序(高阶到低阶或低阶到高阶)是实现定义的。

C 2018 6.2.6.2 说无符号整数用纯二进制表示,脚注表明这意味着归因于连续位的值是 2 的连续幂。所以必须有一些位的“连续”,它们在连续中的位置对应于它们的值的顺序。但是,不可能将此顺序与任何硬件属性相关联,因为 C 中没有任何内容使位可单独寻址,因此 C 中没有机制来识别比另一个地址低的位或以其他方式检查任何位中的单个位内存单元(无论是在寄存器、主内存还是其他地方)。

C 标准没有为程序提供任何方法来请求实现以特定方式对位进行排序。

如果您希望以相反的顺序分配位域,您可以颠倒它们的声明。但是,这不会在以其他顺序分配位字段的 C 实现中保持该顺序。

根据 GCC 10.3 documentation 第 4.9 节,单元内的位字段顺序是“由 ABI 确定”,这意味着它遵循目标平台的应用程序二进制接口。所以我希望命令不能通过命令行开关选择。我也没有看到预定义的预处理器宏来报告它。

无论如何,使用命名位域通常不是实现位“数组”的好方法。您可以简单地使用位运算符来访问单元中的位,并且可以根据需要编写函数来设置和获取它们:

unsigned int GetBit(UnitType u, int n) { return (u >> n) & 1; }
void SetBit(UnitType *u, int n, UnitType b) { *u ^= (((*u >> n) & 1) ^ b) << n; }
相关问题