C 结构解释与位域的配合不正确

问题描述 投票:0回答:2

我需要使用不同的 C 结构(网络头描述符)对内存中一个字节的 2 位(来自线路)进行相同的解释。这是最小的可重现示例:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

struct some {
        uint8_t reserved : 6;
        uint8_t flags : 2;
} __attribute__((packed));

struct some2 {
        uint16_t b : 12; 
        uint16_t reserved : 2;
        uint16_t flags : 2;
} __attribute__((packed));

int main(void)
{
        char *ptr = malloc(8);
        ptr[0] = 0xC0;
        ptr[1] = 0x00;

        struct some *hdr = (struct some *)ptr;
        printf("%lu %u\n", sizeof(struct some), hdr->flags);

        struct some2 *hdr2 = (struct some2 *)ptr;
        printf("%lu %u\n", sizeof(struct some2), hdr2->flags);

        return 0;
}

输出:

1 3
2 0

将第二个结构体中的 flags 解释为 0 的原因是什么? 在 C 中使用位字段时的字段顺序 假设

C 标准允许编译器以任意顺序放置位域。没有 可靠且便携的方式来确定订单。

但是编译器代码没有通过位域机制,这只是来自网络的一个字节,我正在通过位域机制解释它..

c linux memory struct bit-fields
2个回答
0
投票

struct some
中,您已告诉编译器布置一个六位字段和一个两位字段。在
struct some2
中,您已告诉编译器布置一个 12 位字段、一个两位字段和另一个两位字段。

编译器这样做了。对于第一个结构,它将六位

reserved
字段布局为第一个(也是唯一)字节的位 0-5,并将两位
flags
字段布局为该字节的位 6-7 。 (这里,位的编号为 0 作为二进制数字解释时具有最低有效值的位置,7 为最高有效值。)

对于第二个结构,它将 12 位

b
字段布局为第一个字节的位 0-7 和第二个字节的位 0-3(等效地,由
uint16_t
形成的位 0-11)两个字节(按小端顺序),两位
reserved
字段作为第二个字节的位 4-5,两位
flags
字段作为第二个字节的位 6-7。

hdr->flags
中,您使用struct some类型访问了一个字节,该字节已设置为C0
16
。这将字节的第 6-7 位解释为两位
flags
字段,产生 3.

hdr2->flags
中,您使用
struct some2
类型访问了两个字节,其中第二个字节尚未设置为任何值。这将第二个字节的第 6-7 位解释为两位
flags
字段。该字节显然在这些位中包含零,至少在效果上是这样,产生 0。

如果您想依赖编译器的位字段布局,那么您需要以不同的方式定义结构,以便

flags
struct some2
字段对应于第一个字节的位 6-7。或者,您可以使用字符类型访问字节并使用移位运算符提取位 6-7。


0
投票

在具有 8 位

char
的小端机器上,
uint16_t
将为 0x00C0。

如果字段按从最不重要到最重要的顺序排列,

  • hdr->flags
    相当于

    ( x >> 6 ) & 0x3             # 3
    
  • hdr2->flags
    相当于

    ( x >> ( 12 + 2 ) ) & 0x3    # 0
    
© www.soinside.com 2019 - 2024. All rights reserved.