c - 如何在 C 运行时以可在其余代码中使用的方式强制转换 void 指针?

标签 c casting void-pointers

这不是“如何将混合数据类型(int、float、char 等)存储在数组中?”问题请仔细阅读! 假设我有以下 void 指针,直到运行时我才知道它的类型:

void* data;

现在,当我知道 data 的类型时,我知道我可以执行以下操作(例如 int ):

int typed_data = *(int*)data;

使用 switch case语句我可以检查一个变量来确定要执行的转换:

switch(type_id) {
    case INT:
        int typed_data = *(int*)data;
        break;
    case FLOAT:
        float typed_data = *(float*)data;
        break;
    // ...
    // etc.
}

但是,这样我将无法访问 switch block 之外的 typed_data,请考虑以下功能作为示例;它需要两个void指针,并根据type_id的值,它会转换 sx更正数据类型,然后使用新定义的类型化数据执行其他操作:

int sequential_seach(int n, void* s, void* x, type_id) {
    int location = 0;
    switch(type_id) {
        case INT:
            int *list = s;
            int element = *(int*)x;
            break;
        case FLOAT:
            float *list = s;
            float element = *(float*)x;
            break;
            // ...
            // etc.
    }

    while(location < n && list[location] != element) { // <---This will cause a compile error

        location++;
        if(location > n - 1) {
            location = -1;
        }
    }
    return location;
}

在上面的函数中locationlist无法在 swtich 之外访问 block ,即使 type_id 匹配 case 之一值并且它们被定义,它们仍然超出范围,在 switch 之外 block ,因此当编译器到达 while 行时居住,它提示 locationlist没有定义。但函数需要这些类型变量。那么如何解决这个问题呢?我应该复制粘贴 while阻止每个 case ?这看起来不是一个很好的解决方案。如果我有一个较长的代码,需要在 100 个不同的地方使用这些变量怎么办?

最佳答案

听起来您需要泛型:使用编译时类型参数定义函数的能力。

不幸的是,C 本身没有泛型。幸运的是,you can use macros as pseudo-generics使预处理器自动生成代码的多个版本。

改编自链接的答案:

// sequential_search.h

/* Provide some helpers that generate a name of the form of sequential_search_T,
    unique for each type argument */

#define TOKENPASTE(x, y) x ## y    
#define SEQ_SEARCH(T) TOKENPASTE(sequential_search_, T)

/* Provide the generic type definition of your function */

int SEQ_SEARCH(TYPE) (int n, void* s, void* x) {
    int location = 0;
    TYPE* list = s;
    TYPE element = *(TYPE*)x;

    while(location < n && list[location] != element) {
        location++;
        if(location > n - 1) {
            location = -1;
        }
    }

    return location;
}

为您打算传递的每个类型参数实例化一次:

// sequential_search.c

#define TYPE int
#include "sequential_search.h"
#undef TYPE

#define TYPE float
#include "sequential_search.h"
#undef TYPE

// etc.

最后,创建一个(静态可解析的)调用点,它将打开您拥有的类型 ID(运行时信息),然后立即分派(dispatch)到通用版本之一:

int sequential_search(int n, void* s, void* x, type_id) {
    switch(type_id) {
        case INT: return sequential_search_int(n, s, x);
        case FLOAT: return sequential_search_float(n, s, x);
        // etc.
    }
}

关于c - 如何在 C 运行时以可在其余代码中使用的方式强制转换 void 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34404054/

相关文章:

统计评论字符数的C程序

c++ - 包含在 main.cpp 中的 header 有效,但在类中抛出错误

c - 如何将 (void**) 传递给函数并有效地取消引用/使用任何类型?

C——指向指针数组的指针

c++ - 如何使用 ffmpeg 提取 Xing/LAME 帧?

c++ - 在可变参数中转换特定类型

c# - 如何强制 c# binary int 除法返回 double?

xml - 如何将 xpath 返回的 xml 数组转换为 Postgres 中的 int 数组

c++ - 指向 void* 的类指针

c - 访问 char 数组中结构的空指针