【问题标题】:C: Typecasting with bitfields reverses values?C:使用位域进行类型转换会反转值?
【发布时间】:2023-02-02 16:53:47
【问题描述】:
我正在尝试将字节流(来自串行端口的原始数据)转换为易于使用的结构。我设法在一个最小的工作示例中复制了这个问题:
#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;
}
我希望字段 source 从 0x9A 得到 9 和 destination 从 0x9A 得到 A 所以输出说:
machine 9 says 'Hello!' to machine 10.
但我得到:
machine 10 says 'Hello!' to machine 9.
知道为什么会这样吗?
【问题讨论】:
标签:
c
struct
casting
bit-fields
【解决方案1】:
问题在于您将原始数据解释为数据包结构的方式。字段源和目标被定义为 4 位字段,这意味着它们只能保存 0 到 15 之间的值。但是,当您将原始数据转换为数据包指针时,您将原始数据的第一个字节解释为 8位整数,而不是两个 4 位整数。
要获得所需的行为,您需要从原始数据的第一个字节中提取源和目标的值,并将它们存储在单独的变量中,然后再将它们存储在数据包结构中。这是一种方法:
#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};
unsigned char source = raw[0] >> 4;
unsigned char destination = raw[0] & 0x0F;
packet message;
message.source = source;
message.destination = destination;
memcpy(message.payload, &raw[1], sizeof(message.payload));
printf("machine %d ", message.source);
printf("says '%s' to ", message.payload);
printf("machine %d.
", message.destination);
return 0;
}
此代码应产生所需的输出:
机器 9 说“你好!”加工 10。