【问题标题】:C vector to handle different array type based in argument用于处理基于参数的不同数组类型的 C 向量
【发布时间】: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 听起来可能可行。谢谢

标签: arrays c vector


【解决方案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://stackoverflow.com/a/60454338/584518

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-04
      相关资源
      最近更新 更多