这是我问题的背景。我有这个代码:
typedef enum DType { float32 } DType;
typedef struct Array {
void *data;
DType dtype;
...
} Array;
整个想法是根据字段
data
的值将指针 dtype
转换为适当的类型。虽然每次需要时都可以在 switch
上使用 dtype
,但我想知道是否可以有一个函数/宏封装该逻辑并可在任何需要的地方使用。
为了进一步说明,这是我想出的一个非解决方案:
void *cast_data_pointer(Array *arr) {
switch (arr->dtype) {
case float32:
return (float *) arr->data;
default:
exit(1);
}
}
虽然类型转换逻辑是正确的,但不能使用,因为它需要提前知道将返回哪种指针类型:
Array arr = ...; # with dtype float32
void *data_ptr;
data_ptr = cast_data_pointer(&arr); # wrong because data_ptr is still a void pointer
Array arr = ...; # with dtype float32
float *data_ptr;
data_ptr = cast_data_pointer(&arr); # wrong because it required to know in advance that the function will return a float pointer
拥有这样的函数/宏可以避免重复,并且当我将来向
DType
枚举添加更多数据类型时会更加灵活。
整个想法是根据字段
的值将指针data
转换为适当的类型。 虽然每次需要时都可以在dtype
上使用switch
,但我想知道是否可以有一个函数/宏封装该逻辑并可在任何需要的地方使用。dtype
不,不是你想的那样。
不可能用宏来做你想做的事情,因为宏在编译时工作,消耗和生成源代码。 他们对变量的值一无所知,而这就是你说你想要做出决定的基础。
您也不能使用函数来做到这一点,因为您遇到了问题中描述的问题:您需要知道所选的数据类型才能解释函数结果,或者使用函数结果,例如标记的联合让你回到开始的地方。
更一般地,在 C 中,每个表达式都有一个在编译时已知的数据类型,因此不能根据任何变量的运行时值而变化。 根据变量值选择行为需要使用运行时条件语句和/或条件表达式。
我可以想象各种宏工具,您可以使用它们轻松生成所需的条件代码,但详细信息取决于具体情况。
另一方面,您可能需要考虑以不同的方式解决问题。 有多种选择可供考虑,例如:
创建特定类型的数据类型和相应的函数。 您可以通过准备一个或多个生成所需声明和定义的宏来避免繁琐的重复——这或多或少是 C++ 模板的 C 版本。
通过将适当的函数与数据相关联来实现通用行为,这些函数知道如何正确地将通用数据结构解释为具有适当类型的元素。
qsort()
使用的回调函数就是这种方法的典型示例。 我想你可能需要几个这样的函数,在这种情况下这将相当于一个 vtable。
依靠客户端进行转换。通过让数组管理函数根据指定大小的无类型项工作,使数组管理函数与类型无关。 这也让人想起
qsort()
。