繁体   English   中英

将void指针转换为struct并将其移动给定大小

[英]Cast void pointer to struct and move it given size

我得到了一个包含3种不同结构的二进制文件,这些结构应该读取到程序中。 读取第一个结构后,我将存储其大小,然后假定将我的void指针+第一个结构长度转换为结构ip_hdr *(这是第二个结构),然后读取其所有值。

但是问题是我不明白如何移动空指针。 我已经了解到,void指针与int指针没有相同的算术规则。

我想做这样的事情:

ptr = (struct ip_hdr *)ptr) + (ethRes));

但这无法正常工作,但我收到以下错误消息:

表达式必须是指向完整对象类型的指针

这是我的代码:

#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>

int main()
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    FILE *fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");


    //Pointers and variables
    struct ethernet_hdr eth;
    struct ethernet_hdr *ethPtr;
    struct ip_hdr ip;
    struct ip_hdr *ipPtr;
    struct tcp_hdr tcp;
    struct tcp_hdr *tcpPtr;

    if (fileOpen == NULL)
    {
        printf("Error\n");
    }
    else
    {
        printf("Success\n");
    }

    char ethrr[10];
    fscanf(fileOpen, "%s", ethrr);
    int length = atoi(ethrr);
    printf("Nr: %d\n", length);

    void *ptr;
    ptr = (void *)malloc(length);
    fread(ptr, sizeof(eth), 1, fileOpen);

    int ethRes = sizeof(((struct ethernet_hdr*)ptr)->dhost) +
        sizeof(((struct ethernet_hdr*)ptr)->shost) +
        sizeof(((struct ethernet_hdr*)ptr)->type);
    printf("%d\n", ethRes);
    printf("ptr1: %d\n", &ptr);

    system("pause");
    fclose(fileOpen);


    return 0;
}

我现在它坏了,但是我还没做完。 现在只需要有关指针的帮助。

这是一个使用void指针沿结构数组移动的示例。

编译器不知道void*指针指向的对象的类型。 因此,您有两种选择。 一种是将其转换为指向“正确”类型的指针,然后添加要移动的元素数。 另一种是将所需的字节数添加到unsigned char* (或类似unsigned char* )中。

该操作发生在下面标记为[1][2]上。

#include <stdio.h>

typedef struct {
    int payload;
    double other;
} thingy;

int main(void) {
    thingy athingy[2];//An array of two thingys.
    void* voidptr=athingy; //a pointer to first thingy.

    thingy* nextthingy=((unsigned char*)voidptr)+sizeof(thingy); //[A] next thingy points to second element of array.
    thingy* altnext=((thingy*)voidptr)+1; //[B] Points to the same thing!

    printf("voidptr==%p %zu\n",voidptr,sizeof(thingy));
    printf("nextthingy==%p\n",nextthingy);
    printf("altthingy==%p\n",altnext);

    if(nextthingy==altnext){
        printf("Same\n");
    }else{
        printf("Not same (oh dear)\n"); 
    }
    return 0;
}

典型输出:

voidptr==0x7ffd6909d660 4
nextthingy==0x7ffd6909d664
altthingy==0x7ffd6909d664
Same

实际值可能会有所不同。

警告

如果我理解这个问题,那么要求是遍历一起读取的多个不同struct 由于对齐,这可能会有问题。 详细讨论超出了此问题的范围,但是C可能会在不同类型的成员或对象之间放置或要求填充以确保它们在体系结构上对齐。 例如,将4字节整数放在数字除以4的内存地址上是很常见的。这简化了硬件并提高了性能。

从片段尚不清楚,只要读入的对象将对齐,并且可能需要进一步复制数据和改组。

可能已经考虑到了这一点,但是从提供的信息中看不到这一点。

可能有帮助的是stddef.h定义的,经常被忽略的offsetof(,)宏。

返回类型内成员的偏移量(考虑内部填充)。 例如,通常不能保证(以上):

voidptr+sizeof(payload)==((unsigned char*)voidptr)+offsetof(thingy,other)

假定结构与文件中的任何内容兼容,这应该起作用(通常,将结构“原始”保存到磁盘是个坏主意,结构在内存中的确切布局取决于编译器,并且不够稳定,无法用作文件结构)。文件格式):

const struct ip_hdr * const ip = (struct ip_hdr *) ((struct ethernet_hdr *) ptr + 1);

这会在类型为ethernet_hdr的指针上加上“ 1”,这将使实际的指针值提前以太网头结构的大小。 然后将结果转换为struct ip_hdr *

我想这就是你想做的。 您可以通过将字节添加到char * ,但这有什么意义呢?

您不能直接将其添加到void指针,因为指针算法始终以所指向的内容为单位,并且void没有大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM