c++ - 位域的分配是否特定于不同的 Endianness 实现

标签 c++ c endianness bit-fields

众所周知,我们有两种类型的字节序:大字节序和小字节序。
假设一个整数占用 4 个字节,因此整数 1 的布局应该是 0x01 0x00 0x00 0x00 用于小端和 0x00 0x00 0x00 0x01 大端。
要检查机器是小端还是大端,我们可以编写如下代码:

int main()
{
    int a = 1;
    char *p = (char *)&a;
    // *p == 1 means little endian, otherwise, big endian

    return 0;
}
据我了解,*p分配了第一个八位字节:0x01用于小端和 0x00对于大端(上面两个粗体部分),这就是代码的工作方式。
现在我不太明白位域如何与不同的字节序一起工作。
假设我们有这样一个结构:
typedef struct {
    unsigned char a1 : 1;
    unsigned char a2 : 1;
    unsigned char a6 : 3;
}Bbit;
我们做如下分配:
Bbit bit;
bit.a1 = 1;
bit.a2 = 1;
这段代码是特定于实现的吗?我在问 bit.a1 的值是否和 bit.a21在小端和 0在大端?或者他们绝对是1不考虑不同的字节顺序?

最佳答案

对于位域,不仅定义了字节字节序实现,还定义了位字节序。
C standard 的第 6.7.2.1p11 节关于结构状态:

An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains,whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.


因此,编译器可以自由地按照它认为合适的方式对结构中的位域进行重新排序。作为一个例子,这里是在 Linux 上表示/usr/include/netinet/ip.h 中的 IP header 的结构:
struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
    /*The options start here. */
  };
在这里你可以看到有两个字段是位字段,它们的声明顺序取决于使用的字节序。
所以这意味着如果您通过网络发送原始结构,您不能依赖任何特定的字节(或位)排序。
鉴于您的示例以及一些添加内容以查看表示:
Bbit bit;
bit.a1 = 1;
bit.a2 = 1;
unsigned char *p = (unsigned char *)&bit;
printf("%02x\n", *p);
大端系统可能会打印 a0而小端系统可能会打印 03 .这是假设未使用的位碰巧设置为 0。

关于c++ - 位域的分配是否特定于不同的 Endianness 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65712793/

相关文章:

c++ - 在使用指针之前检查 null

c++ - 在编译时根据字节顺序定义位域

c++ - 如何防止ActiveMQ CPP发送方法永远阻塞?

c++ - 从反向迭代器获取 vector 中的索引

c++ - const TypedeffedIntPointer 不等于 const int *

c - 我不明白一些旧的 C 数组连接

c - (伪)C 中的 OOP 从其函数指针获取结构对象

c - 从类型 'bignum' 分配给类型 'int' 时的类型不兼容

endianness - 为什么条件字节顺序不好?