如何在未对齐的缓冲区中使用结构体

4
在我的网络应用程序中,我想使用一个偏移量作为指向已知结构的指针,而不是使用memcpy() 2次(rx/tx)复制结构的每个字段太重了。我知道我的gcc 4.7.2(选项:-O3)在cortex-a8上可以使用1条指令不对齐地执行memcpy(&a,&buff,4),因此它可以访问未对齐的int。假设它可能有很多结构或大结构,最好的方法是什么?
struct __attribute__ ((__packed__)) msg_struct {
  int a;  //0 offset
  char b; //4 offset
  int c;  //5 offset
  int d[100];  //9 offset
}

char buff[1000];// [0]:header_size [1-header_size]:header [header_size+1]msg_struct

func() {
  struct msg_struct *msg;
  recv ((void *)buff, sizeof(buff));
  msg=buff+header_size; // so, it is unaligned.
  ...
    // some work like:
    int valueRcv=msg->c;
  //or modify buff before send 
  msg->c=12;

  send(buff,sizeof(buff));
}

这个能用于 buff 是一个 int 数组吗?添加 header_size 会使你的指针指向一个非常错误的位置。 - Sergey Kalinichenko
3
确保你理解指针算术的工作原理。 - Kerrek SB
1
编译器选项?除非您采取措施使编译器对此结构进行打包,否则它将使用字段的自然对齐方式 - 这可能不是您想要的。 - marko
首先,你不应该使用与语言、编译器和硬件相关的数据结构作为网络协议。 - user207421
1个回答

3
为了让GCC在处理结构体和它的成员时使用一个字节的对齐方式,请使用GCC的packed属性。该属性的用法可以在这个页面找到。在你的代码中,将以下内容修改:
struct msg_struct {…}

to:

struct __attribute__ ((__packed__)) msg_struct {…}

您还需要纠正指针算术。将header_size添加到buff中,会添加100个int对象的距离,因为buff是指向int的指针。您应该将buff保持为unsigned char数组,而不是int


是的,抱歉,我的问题集中在如何访问接收缓冲区中的结构字段上?例如:int valueRcv = msg->c; 和 msg->c = 12; - David Bonnin
@DavidBonnin:你的代码已经包含了这样的访问。你需要纠正指针算术,以便使用unsigned char正确计算msg,而不是int - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接