我遇到的情况是,在运行时我不知道结构成员的类型。读取一个文件,该文件包含有关struct成员数据类型的信息(稍后将对其进行初始化)。
我想知道是否有办法在运行时将void指针永久转换为另一种类型。我认为类型可以用另一种方式表示(例如存储包含该类型的字符串)。但这会为正确访问void *带来很多开销(每个潜在类型的if语句)。
有任何想法或其他信息吗?
感谢。
答案 0 :(得分:2)
我们认为您的文件格式如下
offset 1: count of elements
offset 2: size of the 1st element
offset 2+1: size of 2nd element
...
offset 2+count-1: size of the last element
offset 2+count: content of 1st element
offset 2+count+size of 1st elem: content of 2nd element
...
并且考虑到你有一个包含3个元素的文件:
1st elem:
size = 2 bytes
content = 0x3412
2nd elem:
size = 1 byte
content = 0xAB
3rd elem:
size = 5 bytes
content = "Hell" (null terminated)
接下来是一个C程序,它创建这样一个文件然后解释它。函数readFile
将适用于任何与前面描述的格式相关的文件。
警告:这只是可以做些什么的一个例子。请注意,未释放分配的内存,也未检查I / O操作!
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct Elem{
int size;
void *content;
};
struct List{
int count;
struct Elem *elems;
};
struct List *list;
void createFile(char *name)
{
FILE *f;
char buf[50];
buf[0] = 3; /* nb elems */
buf[1] = 2; /* size of elem 1 */
buf[2] = 1; /* size of elem 2 */
buf[3] = 5; /* size of elem 3 */
/* elem 1 */
buf[4] = 0x12;
buf[5] = 0x34;
/* elem 2 */
buf[6] = 0xab;
/* elem 3 */
buf[7] = 'H';
buf[8] = 'e';
buf[9] = 'l';
buf[10] = 'l';
buf[11] = '\0';
f = fopen(name, "wb");
fwrite(buf, 12, 1, f);
fclose(f);
}
void readFile(char *name)
{
FILE *f;
char c;
int i;
f = fopen(name, "rb");
/* read number of elements */
fread(&c, 1, 1, f);
list->count = c;
list->elems = (struct Elem*)malloc(sizeof(struct Elem) * c); /* allocate the needed size */
for(i = 0; i < list->count; i++)
{
/* read the size of current element's size */
fread(&c, 1, 1, f);
list->elems[i].size = c;
list->elems[i].content = malloc(c); /* allocate the needed size */
}
for(i = 0; i < list->count; i++)
{
/* read the current element's content */
fread(list->elems[i].content, list->elems[i].size, 1, f);
}
fclose(f);
}
int main(int argc, char **argv)
{
createFile("test");
list = (struct List *)malloc(sizeof(struct List));
readFile("test");
printf("elem 1: %04X\n", *((unsigned short*)list->elems[0].content));
printf("elem 2: %02X\n", *((unsigned char*)list->elems[1].content));
printf("elem 3: %s\n\n", (char*)list->elems[2].content);
/* you should free the allocated memory */
return 0;
}
结果输出为:
elem 1: 3412
elem 2: AB
elem 3: Hell
结构的填充方式如下:
list -> count = 3
elems[0]-> size = 2
content = 0x3412
elems[1]-> size = 1
content = 0xAB
elems[2]-> size = 5
content = {'H', 'e', 'l', 'l', 0}
注意:
您可能已经注意到,将unsigned short
转换为保存为序列{0x12, 0x34}
的元素具有16位值0x3421
。这是因为我的计算机的小端架构在较低地址(see)中存储了较不重要的字节。
答案 1 :(得分:0)
这在C中是不可能的,因为你在编译时不知道运行时的永久转换应该是什么。
(使用C ++,您可以使用静态或动态多态来执行某些操作。)