C:使用位域的类型转换会反转值吗?

nbysray5  于 2023-02-03  发布在  其他
关注(0)|答案(2)|浏览(118)

我试图将一个字节流(来自串口的原始数据)转换成一个结构,以便于使用。我已经设法在一个最小的工作示例中复制了这个问题:

#include <stdio.h>

typedef struct {
    unsigned int source: 4;
    unsigned int destination: 4;
    char payload[15];
} packet;

int main(void)
{
    // machine 9 sends a message to machine 10 (A)
    char raw[20] = {0x9A, 'H', 'e', 'l', 'l', 'o', '!', 0};
    packet *message = (packet *)raw;
    printf("machine %d ", message->source);
    printf("says '%s' to ", message->payload);
    printf("machine %d.\n", message->destination);
    return 0;
}

我希望字段source0x9A中得到9destination0x9A中得到A,这样输出结果就是:

machine 9 says 'Hello!' to machine 10.

但我得到:

machine 10 says 'Hello!' to machine 9.

你知道为什么会这样吗?

eivgtgni

eivgtgni1#

0x9A-最低4位A,最高4位9
在您的结构中,如果使用GCC成员进行编译,则source(占用较低的半字节)被分配为Adestination(占用较高的半字节)被分配为9
所以程序输出是正确的。

1aaf6o9v

1aaf6o9v2#

我试图将字节流(来自串行端口的原始数据)转换为易于使用的结构。

char raw[20] = {0x9A, 'H', 'e', 'l', 'l', 'o', '!', 0};
packet *message = (packet *)raw;

这是一段糟糕的代码,原因有几个。

  • 对齐:当结构packet的对齐需求超过char的对齐需求时,(packet *)raw风险 * 未定义行为 *。
  • 大小:成员.source.destination的大小不能压缩为1个字节。位字段的许多属性取决于实现。raw[](20)的总大小可能与packet不同。
  • 别名。编译器可以假定对raw[20]的更改不会影响message

应该怎么做取决于未发布的大代码。

相关问题