用于访问结构中元素的指针操作

时间:2014-09-11 08:32:49

标签: c struct

鉴于下面的简单代码,你给process_payload一个指向数据包有效负载部分的指针,你如何访问标题部分?理想情况下,调用者应该从头开始简单地给出一个指向完整数据包的指针,但是有些情况下你没有消息的开头并且需要向后工作才能获得头信息。我想这个问题变成了对遍历结构的内存布局的理解。

标头使用sizeof操作计算为8个字节。我假设Visual C ++编译器为标头添加了3个字节的填充。 当执行ptr算法时,pptr和pptr->有效载荷之间的差异是十进制80(不确定为什么这个值?)(pptr-> payload-pptr)。设置ptr =(struct Packet *)(有效载荷 - 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));
 }

1 个答案:

答案 0 :(得分: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);

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


有关上述代码的两点注意事项:

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