我有一个包含3种不同结构的二进制文件,我想这些结构可以读到我的程序。在我读完第一个结构后,我存储它的大小,然后我想将我的void指针+第一个结构长度转换为struct ip_hdr *(这是第二个结构),然后读取它的所有值。
但问题是我不明白你如何移动一个void指针。我知道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;
}
我现在已经破了,但我没有完成它。现在只需要指点帮助。
答案 0 :(得分:3)
这是使用指向void
的指针移动结构数组的示例。
编译器不知道void*
指针指向的对象类型。
所以你有两个选择。一种方法是将其转换为指向“正确”类型的指针,然后添加要移动的元素数。另一种是将所需的字节数添加到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的存储器地址上非常常见。这简化了硬件并提高了性能。
从提供的片段中不清楚读入的对象是否会对齐,可能需要进一步复制数据和改组。
这可能已被考虑在内,但从提供的信息中无法看出。
offsetof(,)
中定义的经常被忽视的stddef.h
宏可能有所帮助。
返回类型中成员的偏移量(考虑内部填充)。例如,通常不保证(上文):
voidptr+sizeof(payload)==((unsigned char*)voidptr)+offsetof(thingy,other)
答案 1 :(得分:2)
这应该有效,假设结构与文件中的任何内容兼容(通常保存结构&#34;原始&#34;到磁盘是一个坏主意,内存中结构的确切布局是依赖于编译器的并且不够稳定,无法用作文件格式):
const struct ip_hdr * const ip = (struct ip_hdr *) ((struct ethernet_hdr *) ptr + 1);
这增加了&#34; 1&#34;指向类型为ethernet_hdr
的指针,它将按以太网报头结构的大小提前实际指针值。然后将结果转换为struct ip_hdr *
。
我认为这就是你想要做的。您可以通过向char *
添加字节来实现,但重点是什么?
你不能直接添加到void指针,因为指针算术总是以指向的为单位,void
没有大小。