簡體   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