繁体   English   中英

纯ANSI-C:制作通用数组

[英]Pure ANSI-C: make generic array

是否可以在纯ANSI-C中复制通用数组?

我有这个结构,它包含一个数组(目前用于浮点数)和一些变量,如数组中的变异大小和容量。

typedef struct _CustomArray
{
    float* array; //the array in which the objects will be stored
    int size; //the current size of the array
    int capacity; //the max capacity of the array
} CustomArray; 

我使用这个结构,所以我可以在纯C中创建一个数组,我可以在其中添加/删除项目,在需要时动态扩展数组大小等所有“标准”数组所做的事情,除了它只用C制作。 现在我想这样做,这样当你初始化这个结构时,你可以设置它应该保存的元素的数据类型,此时它只能存储浮点数据类型,但我想使它能够存储任何数据类型/其他结构。 但我不知道这是否可行。

此时制作此数组的函数是:

CustomArray* CustomArray_Create(int initCapacity, /*type elementType*/)
{
    CustomArray* customArray_ptr; //create pointer to point at the structure
    float* internalArray = (float*)malloc(sizeof(float) * initCapacity); //create the internal array that holds the items
    if(internalArray != NULL)
    {
        CustomArray customArray = { internalArray, 0, initCapacity }; //make the struct with the data
        customArray_ptr = &customArray; //get the adress of the structure and assign it to the pointer
        return customArray_ptr; //return the pointer
    }
    return NULL;
}

是否可以将数据类型作为参数提供,以便我可以为该数据类型的malloc内存并将其作为动态数组中的给定数据类型进行转换?

提前致谢,

Marnix van Rijswijk

你的代码有一个严重的问题...你正在返回局部变量的地址(CustomArray),当函数返回时,该变量被销毁,所以你不能继续使用它与指针。 你还必须使用malloc结构,以便在函数返回后内存仍然可用。

关于使类型成为参数,您可以使用宏来稍微接近...例如:

#include <stdlib.h> 
#define DefArray(type) \
typedef struct T_##type##Array {\
    type *array; \
    int size, capacity; \
} type##Array; \
static type##Array *type##ArrayCreate(int capacity)\
{\
    type##Array *s = malloc(sizeof(type##Array));\
    if (!s) return NULL;\
    s->array = malloc(sizeof(type) * capacity);\
    if (!s->array) { free(s); return NULL; }\
    s->size=0; s->capacity = capacity;\
    return s;\
}

然后你就可以这样使用它

#include "customarray.h"
DefArray(float);
DefArray(double);

void foo()
{
    floatArray *fa = floatArrayCreate(100);
    ...
}

请注意,您必须使用宏来定义所有自定义函数。 另请注意,此方法将复制每个模块中的代码(我说不是一个大问题,但如果您不能使用C ++,则可能您的目标平台非常小)。 使用稍微复杂的方法,您可以为实现生成单独的.h文件和.c文件。

男孩,这听起来像是C ++的工作。

我认为你在C中最接近这个是不通过类型,而是大小(sizeof(type))。

您可以使您的函数更通用,以便它可以执行它需要做的事情,如果它只知道数组中每个项目的大小。 这就是像bsearch()这样的函数的工作方式。

实现此目的的一种方法是使用所谓的X宏

是使用这种技术的(可能是错误的)通用矢量实现。

然后用它作为

// defining generic parameters
#define PREFIX tv
#define ITEM token
#define NAME token_vector
#include "vector.h"

...
token_vector tv = tv_new(100);
*(tv.front) = some_token;
tv_push_back(&tv, other_token);

几年前,我在C语言中乱用通用编程,只是为了它。

基本上,我最终利用了预处理器。 我想我有点成功:我确实为几个最重要的通用数据结构完成了一些宏表示法。

我绝对没有完成的任务(至少以任何自动方式)是递归运行宏 - 即创建数组数组或哈希数组等。这是由于C预处理器有趣的咳嗽疯狂咳嗽语义宏。

如果您有兴趣,请输入以下代码: https//github.com/christianfriedl/CGenerics/blob/master/src/cgArray.h

因此,对于没有自己声明类型的对象,存在“有效类型”的概念。 (因为它震动了,那几乎只包括“* alloc指针的另一端”和一些奇怪的联合规则)基本上,这种对象的“有效类型”是你上次用来赋予它的任何东西,不计算charchar[]因为原因。

一个有趣的交互与声明结构类型的规则有关。 也就是说,您可以自由地重新声明相同的标记名称(或缺少标记名称),并且每个声明都引入了一个全新的类型(过去的名称被遮蔽,但旧类型的对象不会被重新解释)。

所以你可以这样做:

# define DECL_VECTOR(NAME,TYPE,SIZE) PUN_STRUCT(NAME,TYPE,SIZE)  INIT_STRUCT(NAME,TYPE,SIZE) 

# define PUN_SIZE sizeof(void*)+sizeof(int)*2


# define PUN_STRUCT(NAME,TYPE,SIZE)                      \
   struct {                                              \
      TYPE (*p)[(SIZE)];                                 \
      int size;                                          \
      int capacity;                                      \
   } *NAME = malloc(PUN_SIZE);                        


# define INIT_STRUCT(NAME,TYPE,SIZE)  do {               \
   if (!NAME) {                                          \
        perror("malloc fail");                           \
        abort();                                         \
   }else {                                               \
        NAME->size = (SIZE);                             \
        NAME->capacity = 0;                              \
        NAME->p = malloc(sizeof(*NAME->p));              \
        if (!NAME->p) {                                  \
            perror("malloc fail");                       \
            abort();                                     \
        }                                                \
        NAME->p = (TYPE(*)[(SIZE)])(NAME->p);            \
   }                                                     \
   }while(false)


int main(int argc, char *argv[]) 
 {

   DECL_VECTOR(vec1,int,8);


    printf("size of handle struct:  %zu,\n\
size of vector array:   %zu,\n\
size of vector element: %zu\n\
address of handle struct: %p,\n\
address of vector array:  %p\n",  sizeof(*vec1),       \
                                  sizeof(*vec1->p),    \
                                  sizeof(*vec1->p[0]), \
                                  vec1,                \
                                  vec1->p);
   free(vec1->p);
   free(vec1);
   return 0;
 }

(但是,人们可能会指责你滥用你的宏权限,而且他们可能并非完全错误)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM