[英]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()这样的函数的工作方式。
几年前,我在C语言中乱用通用编程,只是为了它。
基本上,我最终利用了预处理器。 我想我有点成功:我确实为几个最重要的通用数据结构完成了一些宏表示法。
我绝对没有完成的任务(至少以任何自动方式)是递归运行宏 - 即创建数组数组或哈希数组等。这是由于C预处理器有趣的咳嗽疯狂咳嗽语义宏。
如果您有兴趣,请输入以下代码: https : //github.com/christianfriedl/CGenerics/blob/master/src/cgArray.h
因此,对于没有自己声明类型的对象,存在“有效类型”的概念。 (因为它震动了,那几乎只包括“* alloc指针的另一端”和一些奇怪的联合规则)基本上,这种对象的“有效类型”是你上次用来赋予它的任何东西,不计算char
或char[]
因为原因。
一个有趣的交互与声明结构类型的规则有关。 也就是说,您可以自由地重新声明相同的标记名称(或缺少标记名称),并且每个声明都引入了一个全新的类型(过去的名称被遮蔽,但旧类型的对象不会被重新解释)。
所以你可以这样做:
# 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.