用于处理基于参数的不同数组类型的 C 向量

Posted

技术标签:

【中文标题】用于处理基于参数的不同数组类型的 C 向量【英文标题】:C vector to handle different array type based in argument 【发布时间】:2020-08-17 12:57:38 【问题描述】:

我正在研究 C 中的向量,即动态可调整大小的数组。我已经实现了一个处理 char 数组的方法。

但是,如果我想为不同类型的数组(int、long 等)提供相同的功能,我必须重新完成整个事情,并且使用不同的名称让它们不串通,因为它们会在同一个命名空间中。

我的问题是:有没有办法根据传递给初始化函数的某个参数来处理 int 数组或 char 数组?

假设我有一个 struct Vector,其成员是 char 指针。就目前而言,当我运行 init 函数时,它会为这个 char 指针分配内存以用作 char 数组。

我能否做到这一点,例如,根据传递给 init 的某个参数,它将为 int 数组而不是 char 数组分配内存?

我一直在考虑这个问题,这将涉及使用 void 指针并在很多地方进行强制转换。还有其他方法/最好的方法是什么?

【问题讨论】:

您是否在寻求一种方法来改进您编写的已经有效的东西?如果是这样,请将其发布到Code Review。但如果你这样做,我建议你发布代码,而不是它的描述。花点时间阅读how to ask a good question。 可以使用union的指针。 @kaylum 听起来可能可行。谢谢 【参考方案1】:

它不能以非常简洁的方式完成,但它是可能的。这是一个例子:

enum vec_type  CHAR, INT, DOUBLE ;

struct vector 
    enum vec_type vec_type;
    void *data;
;

struct vector *vec_realloc(struct vector *vec, enum vec_type vec_type, size_t n)

    size_t elsize;
    switch(vec_type) 
        case CHAR:   elsize = sizeof(char);   break;
        case INT:    elsize = sizeof(int);    break;
        case DOUBLE: elsize = sizeof(double); break;
    
    struct vector *ret = realloc(vec, elsize * n);
    return ret;

是的,我知道 sizeof(char) 总是计算为 1,但在这种情况下,我认为它看起来要好得多。

【讨论】:

【参考方案2】:

您可以使用泛型宏来实现它:

简单示例:

int* vec_alloc_int (size_t n)

  return malloc(sizeof(int[n]));


char* vec_alloc_char (size_t n)

  return malloc(sizeof(char[n]));


#define vec_alloc(type, n) _Generic( (type[])0[0],      \
                                    int:  vec_alloc_int,  \
                                    char: vec_alloc_char)(n)

用法:

int*  i = vec_alloc(int, 5);
char* c = vec_alloc(char, 5);

解释:

(type[])0[0] 的技巧是创建一个包含 1 项的 复合文字 数组,然后取消引用该数组的第 1 项。这会将宏参数从类型转换为对象,可以传递给_Generic_Generic 然后选择合适的函数来使用。


优点:

类型比 void 指针更安全。 类型在编译时解析,而不是在运行时解析。

缺点:

必须列出所有支持的类型,每种类型都有单独的函数。 无法使用恐龙编译器 (C90/C99)。

上面的邪恶“X-macro”版本(我不会真的推荐)看起来像这样:

#include <stdio.h>
#include <stdlib.h>

#define SUPPORTED_TYPES(X) \
  X(int)                   \
  X(char)                  \
  
#define define_vec_alloc(type)    \
type* vec_alloc_##type (size_t n) \
 return malloc(sizeof(type[n])); 

SUPPORTED_TYPES(define_vec_alloc)

void* vec_alloc_dummy (size_t param)
#define GENERIC_LIST(type) type: vec_alloc_##type,
#define vec_alloc(type, n) _Generic((type[])0[0], SUPPORTED_TYPES(GENERIC_LIST) default: vec_alloc_dummy)(n)

int main(void)

  int*  i = vec_alloc(int,  5);
  char* c = vec_alloc(char, 5);

此处解释:https://***.com/a/60454338/584518

这个版本非常难读,但避免了所有形式的代码重复,这就是它获得的唯一好处。

【讨论】:

以上是关于用于处理基于参数的不同数组类型的 C 向量的主要内容,如果未能解决你的问题,请参考以下文章

R语言数据结构二

基于 C++17 中的范围,用于自定义容器或具有不同开始/结束类型的通用类

在向量中读写不同类型

如何将向量作为参数传递给另一个向量?

R语言实战-数据类型-1(标量向量矩阵数组)

基于可选函数参数的不同返回类型 - Typescript