c中结构的类型转换数组

c中结构的类型转换数组,c,structure,C,Structure,我有一个这样的结构 struct packet { int seqnum; char type[1]; float time1; float pri; float time2; unsigned char data[512]; } 我正在接收数组中的数据包 char buf[529]; 我想把seqnum、data和所有东西分开。下面的类型转换工作吗。。它给了我垃圾的价值 struct packet *pkt; pkt=(struct packet *)buf; printf(" %d",p

我有一个这样的结构

struct packet
{
int seqnum;
char type[1];
float time1;
float pri;
float time2;
unsigned char data[512];
}
我正在接收数组中的数据包

char buf[529];
我想把seqnum、data和所有东西分开。下面的类型转换工作吗。。它给了我垃圾的价值

struct packet *pkt;
pkt=(struct packet *)buf;
printf(" %d",pkt->seqnum)

不,这可能行不通,而且通常是一种不好的、不可靠的做法

您必须使用特定于编译器的扩展来确保结构成员之间没有不可见的填充,这样才能工作。例如,对于gcc,您可以使用语法来完成这项工作

因此,这不是一个可移植的想法


最好是明确地说明它,并将每个字段解包。这也让您有机会在网络协议中有一个定义良好的endianness,这对于互操作性来说通常是一个好主意。

不,这通常不是有效的代码。您应该先创建结构,然后将memcopy内容复制到其中:

packet p;

memcpy(&p.seqnum, buf + 0, 4);

memcpy(&p.type[0], buf + 4, 1);

memcpy(&p.time1, buf + 5, 4);
等等


您必须非常小心,以获得正确的类型大小和endianness。

首先,您无法事先知道编译器将在结构中插入填充字节以进行性能优化(缓存线对齐、整数对齐等),因为这取决于平台。当然,除非你考虑只在你的平台上构建应用程序

无论如何,在您的情况下,您似乎是从某处(网络?)获取数据,并且很可能数据已被压缩(字段之间没有填充字节)

如果确实要将数组类型转换为结构指针,仍然可以告诉编译器删除它可能添加的填充字节。请注意,这取决于您使用的编译器,而不是标准的C实现。使用gcc,您可以在结构定义的末尾添加以下语句:

struct my_struct {
    int blah;
    /* Blah ... */
} __attribute__((packed));
请注意,这将影响成员访问、复制等的性能

除非你有很好的理由这样做,否则永远不要使用
\uuuu属性(packed))
东西


另一个更可取的解决方案是自己进行解析。您只需分配一个适当的结构,并通过从缓冲区中寻找良好的信息来填充其字段。一系列
memcpy
指令可能会在这里起作用(参见Kerrek的答案)

尝试读取大量字节:
char buf[sizeof(struct packet)]和:读取(fd、buf、sizeof(结构数据包))
@Marcassin:确保读取的字节数等于结构的大小,但它不会更改传入的字节,因此不会确保它们具有与结构匹配的填充或结尾。如果传入的字节在
字符类型[1]
浮点时间1
之间没有三个字节,但是结构有,那么
读取
就完全中断了。为了美观起见,永远不要键入
请帮我输入代码。
短语againDo您想要一个在标准C中工作的解决方案,还是想要一个用于特定C实现的解决方案?哪个实现(包括哪个目标平台)?@Eric Postdischil我正在ubuntuth中使用gcc编译器运行此实现特定于编译器的
\uuuuu属性\uuuuuuu((打包))
不是标准C,但如果在多个平台上使用相同的编译器,则仍然有效。顺便说一句,OP的上下文似乎暗示了一些与网络相关的代码,因此,数据包是打包的,因此建议这样做。@EricPostchil我编辑了我的答案以使其更清楚。
\uuuu属性\uuuu
限制了代码段的可移植性,因为某些编译器可能没有集成所需的属性,但是如果在多个平台上一直使用同一个编译器,那么跨平台的可移植性是否仍然存在?(我这样问是为了澄清我的想法:))如果它得到支持,
\uuuuu属性(packed))
解决了填充问题,但没有解决端点问题或其他有关值如何编码/表示的问题(例如,
float
类型是否使用IEEE 754或
int
类型有多大)。有两种方法可以解决这个问题:用标准C写,单独读取每个字节并使用算术等转换为本机类型,或者用
struct
中完全定义并依赖于实现的字节为特定实现和目标写。您好,谢谢。你能告诉我如何解包上面例子中的每个字段吗。