【问题标题】:Pointer manipulation to access elements in a struct指针操作以访问结构中的元素
【发布时间】:2014-11-05 03:01:39
【问题描述】:

给定下面的简单代码,其中 process_payload 被赋予了一个指向数据包有效负载部分的指针,你如何访问标题部分?理想情况下,调用者应该从头开始简单地给出一个指向完整数据包的指针,但在某些情况下,您没有消息的开头,需要向后工作以获取标头信息。我猜这个问题变成了对遍历一个结构体的内存布局的理解。

使用 sizeof 操作将标头计算为 8 个字节。我假设 Visual C++ 编译器在标题中添加了 3 个字节的填充。 在做 ptr arith (pptr->payload - pptr) 时,pptr 和 pptr->payload 的区别是十进制 80(不知道为什么这个值??)。设置 ptr = (struct Packet*)(payload - 80) 有效,但似乎更像是一种黑客行为。我不太明白为什么减去 sizeof(struct header) 不起作用。

感谢您提供的任何帮助。

struct Header
{
    unsigned char id;
    unsigned int size;
};

struct Packet
{
    struct Header header;
    unsigned char* payload;
};


void process_payload(unsigned char* payload);

int main()
{
    struct Packet* pptr = (struct Packet*)malloc(sizeof(struct Packet));
    pptr->payload = (unsigned char*)malloc(sizeof(unsigned char)*10);

    process_payload(pptr->payload);

    return 1;
}

// Function needs to work backwards to get to header info. 
void process_payload(unsigned char* payload)
{
    // If ptr is correctly setup, it will be able to access all the fields
    // visible in struct Packet and not simply payload part.
    struct Packet* ptr;

    // This does not work when intuitively it should?
    ptr = (struct Packet*)(payload - sizeof(struct Header));
 }

【问题讨论】:

  • 检查(非标准)container_of宏,可以看到here
  • pptr in main() 在这段代码中毫无意义。在我看来,您正在尝试(但没有成功)为实际有效负载制作 flexible array member
  • 正如 WhozCraig 所说,您一定在尝试做某事:我看不出不直接将 struct Packet * 传递给 process_payload() 的意义
  • 你可能想在 malloc 之后初始化你的结构或使用 calloc,在你的 sn-p 中它们未初始化。

标签: c struct


【解决方案1】:

这是因为在main 中分配了两个 指针,并将第二个指针传递给process_payload 函数。这两个指针不相关。

有两种方法可以解决这个问题,它们都包含一个分配。

第一个解决方案是使用所谓的灵活数组,在结构中最后有一个数组成员,没有任何大小:

struct Packet
{
    struct Header header;
    unsigned char payload[];
};

要使用它,您需要进行一次分配,结构的大小加上有效负载的大小:

struct Packet *pptr = malloc(sizeof(struct Packet) + 10);

现在pptr->payload 的处理方式类似于指向 10 个无符号字符的普通指针。

另一种解决方案,它是您当前解决方案和灵活数组解决方案的混合,是进行一次分配并使payload 指针指向单个分配的内存块中的正确位置:

struct Packet
{
    struct Header header;
    unsigned char *payload;
};

// ...

struct Packet *pptr = malloc(sizeof(struct Packet) + 10);
pptr->payload = (unsigned char *) ((char *) pptr + sizeof(struct Packet);

请注意,在这种情况下,要从payload 指针中获取Packet 结构,您必须使用sizeof(Packet) 而不仅仅是sizeof(Header)


上面的代码有两点需要注意:

  1. don't cast the result of malloc
  2. sizeof(char)(以及unsigned char 的大小)被指定为始终为1,因此不需要sizeof

【讨论】:

  • 非常感谢您的回答。我以前见过灵活的指针,但从来没有真正确定为什么会这样。现在我明白了。也感谢您的说明。
猜你喜欢
  • 2011-06-04
  • 2013-06-11
  • 2017-01-04
  • 2020-11-05
  • 1970-01-01
  • 2023-02-16
  • 2013-05-26
  • 1970-01-01
  • 2014-02-19
相关资源
最近更新 更多