我有一个缓冲区,并希望将其转换为结构的指针:
#include <stdint.h>
#include <stdio.h>
struct __attribute__((packed)) req {
uint8_t a;
uint16_t b;
uint8_t *c;
};
void f(uint8_t *Buf)
{
struct req *r = (struct req *)Buf;
printf("a: %02x\n", r->a);
printf("b: %04x\n", r->b);
printf("c: %02x\n", r->c[0]);
}
int main()
{
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04 };
f(buf);
return 0;
}
该示例不起作用,因为第4个字节不是地址,而是实际数据。我可以修理&#34;这通过手动设置指针:
r->c = &Buf[3];
有没有办法用演员表演这个?
答案 0 :(得分:2)
有没有办法用演员表演这个?
不,原因有很多:
在这种情况下,您必须手动反序列化数据:
struct req r = { buf[0],
(uint16_t)buf[1]<<8 | buf[2], // assumes big endian
&buf[3] };
在这里,我们注意到代码也依赖于endianess。因此,您必须知道此数据来自的系统/协议的字节顺序,以便正确地对其进行反序列化。
答案 1 :(得分:0)
有什么方法可以通过演员表吗?
是的,根据以下假设,是可能的:
您需要注意结构对齐(特定于编译器):
#pragma pack(push, 1) ... #pragma pack(pop)
,
__attribute__((packed))
等
您需要注意架构与缓冲区中字节之间的字节序(如果需要,请进行转换)
您可以做的是在结构中使用void* c
而不是uint8_t* c
,然后将void*
强制转换为显式指针类型。
#include <stdint.h>
#include <stdio.h>
#pragma pack(push, 1)
typedef struct {
uint8_t a;
uint16_t b;
void* c;
} req;
#pragma pack(pop)
void f(uint8_t* Buf)
{
req* r = (req*)Buf;
printf("a: %02x\n", r->a);
printf("b: %04x\n", r->b);
printf("c: %02x\n", ((uint8_t*)&r->c)[0]);
}
int main()
{
uint8_t buf[] = { 0x01, 0x02, 0x03, 0x04 };
f(buf);
return 0;
}
输出:
a: 01
b: 0302
c: 04
#include <stdint.h>
#include <stdio.h>
#pragma pack(push, 1)
typedef struct {
uint8_t a;
uint16_t b;
void* c;
} req;
typedef struct {
uint8_t cmd;
uint16_t value;
} SubPacket;
#pragma pack(pop)
void f(uint8_t* Buf)
{
req* r = (req*)Buf;
printf("a: %02x\n", r->a);
printf("b: %04x\n", r->b);
SubPacket* sub_packet = (SubPacket*)&r->c;
printf("cmd: %02x\n", sub_packet->cmd);
printf("value: %04x\n", sub_packet->value);
}
int main()
{
uint8_t buf[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
f(buf);
return 0;
}
输出:
a: 01
b: 0302
cmd: 04
value: 0605
答案 2 :(得分:-2)
#include <stdint.h>
#include <stdio.h>
struct __attribute__((packed)) req {
uint8_t a;
uint16_t b;
uint8_t c[]; /* <--- Use this notation to be able to achieve this */
};
void f(uint8_t *Buf)
{
struct req *r = (struct req *)Buf;
printf("a: %02x\n", r->a);
printf("b: %04x\n", r->b);
printf("c: %02x\n", r->c[0]);
}
int main()
{
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04 };
f(buf);
return 0;
}