【问题标题】:Permanent casting of void pointer at runtime在运行时永久转换 void 指针
【发布时间】:2014-06-12 13:25:34
【问题描述】:

我的情况是直到运行时才知道结构成员的类型。读取一个文件,该文件包含有关结构成员数据类型的信息(稍后将对其进行初始化)。

我想知道是否有办法在运行时将 void 指针永久转换为另一种类型。我在想该类型可以用另一种方式表示(例如存储一个包含该类型的字符串)。但这会带来大量开销来正确访问 void*(每个潜在类型的 if 语句)。

有什么想法或其他信息吗?

谢谢。

【问题讨论】:

  • “永久”是什么意思?
  • #define SOMETHING_I_WILL_KNOW_LATER void*; SOMETHING_I_WILL_KNOW_LATER 我的结构;获得信息后,#undef SOMETHING_I_WILL_KNOW_LATER 并用正确的值重新定义它。
  • 显示您的代码,我们可能会准确了解您希望实现的目标(因为您的问题不是很清楚),以及是否可能。
  • 在那种情况下,为什么还要麻烦结构呢?只需分配一些内存并根据需要使用它。
  • 您可能想在 C 中使用一种通用对象方法。您应该提供一些您希望使用的代码。

标签: c pointers casting void


【解决方案1】:

假设您的文件具有以下格式

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,但您也许应该谈谈字节序。
  • @Zack 当然!我不想谈论无关紧要的事情,但我会按照你的要求补充一点。
【解决方案2】:

这在 C 中是不可能的,因为您在编译时不知道运行时的永久转换应该是什么。

(使用 C++,您可以使用静态或动态多态性来做一些事情。)

【讨论】:

  • 我想说在 C 中没有什么是不可能 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 2012-11-02
  • 2015-02-14
  • 2016-01-12
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
相关资源
最近更新 更多