【发布时间】:2014-10-30 09:59:30
【问题描述】:
我做了这个联合,以便轻松地在位和整数之间来回访问。 (事实上,我寻找了一种方法来轻松地读取 / 写入有符号整数的所有位,没有可移植性陷阱,我把自己搞砸了)
typedef union {
struct {
unsigned int b32 : 1;
unsigned int b31 : 1;
unsigned int b30 : 1;
unsigned int b29 : 1;
unsigned int b28 : 1;
unsigned int b27 : 1;
unsigned int b26 : 1;
unsigned int b25 : 1;
unsigned int b24 : 1;
/* etc. */
unsigned int b01 : 1; /* LSB */
} field;
uint32_t word;
int32_t integer;
} Bit32Field_T;
正如预期的那样,每个 bxx 字段都允许我访问底层 32 字节整数的位。
但是,此代码仅对 sparc(大端)CPU 有效。对于 little-endian (x86),我必须镜像从 b01 到 b32 的每个字段,以获得预期的行为。
typedef union {
struct {
unsigned int b01 : 1; /* LSB */
unsigned int b02 : 1;
unsigned int b03 : 1;
unsigned int b04 : 1;
unsigned int b05 : 1;
unsigned int b06 : 1;
unsigned int b07 : 1;
unsigned int b08 : 1;
unsigned int b09 : 1;
/* etc. */
unsigned int b32 : 1;
} field;
uint32_t word;
int32_t integer;
} Bit32Field_T;
我认为 little-endianness 是关于反转字节而不是位!我应该如何理解做的位包装?
(一切都是用 gcc 编译的,对于 BE 在 solaris 下,对于 LE 在 debian 下)
【问题讨论】:
-
这与 endienness 本身无关;位的排列似乎是compiler-dependent。如果你想要可移植的代码,你最好使用
(x.word >> bit) & 1。 -
我自己解决了一个类似的问题,对我来说,将小端转换为大端是关于反转字节而不是位,我在反转位而不是字节之后意识到这一点..也许是关于你是否在一个 #define大/小系统然后是两个联合声明的适当#ifdef?不理想,因为它需要重建,但总比没有好?
-
您的号码是 32 位整数。它由一行 4 个字节组成。这些字节在不同架构上的排序可能不同...
-
1) 字节序问题通常是面向字节的问题,但位字节序问题确实存在。 2)为了最大的便携性,考虑
unsigned可能有不同的大小。也许使用固定大小的,比如uint16_t3) 为了获得最大的便携性,请遵循@M Oehm 的建议:使用轮班。 -
C 标准要求您的编译器记录它如何在位字段中对其位进行排序,因此您可以尝试查找该文档(如果不存在则提交错误报告)。跨度>
标签: c unions bit-fields