首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >创建一个可以接受C语言中任何类型的动态数组

创建一个可以接受C语言中任何类型的动态数组
EN

Stack Overflow用户
提问于 2017-02-17 16:42:43
回答 3查看 4.9K关注 0票数 22

我正在尝试找到一种方法来创建一个结构来保存一个可以与任何数据类型(包括用户定义的数据类型)一起工作的动态数组,到目前为止,这就是我想出来的。

代码语言:javascript
复制
#define Vector(DATATYPE) struct {   DATATYPE* data; size_t size; size_t used; }

typedef Vector(int) int_Vector;

int main(int argc, char* argv[]){
    int_Vector vec;
    return 0;
}

当这个方法起作用的时候,我在想,这是一个好的实践吗?我应该做这样的事情吗?还是有更好的方法?此外,还有一种方法可以在不使用typedef Vector(int) int_vector部件的情况下实现此功能。基本上,这是一种让我能够像c++使用模板一样使用数组的方法,它看起来像这样:

代码语言:javascript
复制
#define Vector(DATATYPE) struct {   DATATYPE* data; size_t size; size_t used; }

int main(int argc, char* argv[]){
    Vector(int) vec;
    return 0;
}

主要是为了避免太多的typedefs,并将所有类型都放在一个名称下。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-02-17 16:51:29

不,C没有模板系统,所以你不能使用模板系统。

你可以像你一样用宏来模拟效果(相当巧妙的解决方案),但是这当然有点不标准,并且需要你的代码的用户来学习宏及其限制。

通常C代码不会尝试,因为它太笨拙了。

最“通用”的典型向量类似于glib的GArray,但这并不能假装知道每个元素的类型。取而代之的是,这留给用户在访问时关心,并且数组只是将每个元素建模为n字节。

C11中的_Generic()可能会有一点帮助,老实说,我在这方面经验不是很丰富。

票数 17
EN

Stack Overflow用户

发布于 2017-02-17 17:08:12

第二个示例不起作用,因为这两个变量被定义为不同的类型,即使它们的成员是相同的。为什么会这样,在我的existing answer中有介绍。

但是,使用稍微不同的方法可以保持语法不变:

代码语言:javascript
复制
#include <stdlib.h>

#define vector(type)    struct vector_##type

struct vector_int
{
    int* array;
    size_t count;
} ;

int main(void)
{
    vector(int) one = { 0 };
    vector(int) two = { 0 };

    one = two;
    ( void )one ;

    return 0;
}

它的用法与C++的vector<int>惊人地相似,完整的例子可以在这里看到:

代码语言:javascript
复制
#include <stdlib.h>

#define vector_var(type)    struct vector_##type

struct vector_int
{
    int* array;
    size_t count;
};

void vector_int_Push( struct vector_int* object , int value ) 
{
    //implement it here
}

int vector_int_Pop( struct vector_int* object ) 
{
    //implement it here
    return 0;
}    

struct vector_int_table
{
    void( *Push )( struct vector_int* , int );
    int( *Pop )( struct vector_int* );

} vector_int_table = { 
                         .Push = vector_int_Push ,
                         .Pop = vector_int_Pop 
                     };

#define vector(type)   vector_##type##_table

int main(void)
{
    vector_var(int) one = { 0 };
    vector_var(int) two = { 0 };

    one = two;

    vector(int).Push( &one , 1 );
    int value = vector(int).Pop( &one );
    ( void )value;

    return 0;
}
票数 6
EN

Stack Overflow用户

发布于 2017-02-17 17:14:02

还不错。我看不出有什么坏处。为了解释另一种方法,在这种情况下最常用的方法是使用联合:

代码语言:javascript
复制
typedef union { int i; long l; float f; double d; /*(and so on)*/} vdata;
typedef enum  {INT_T,LONG_T,FLOAT_T, /*(and so on)*/} vtype;
typedef struct 
{
    vtype t;
    vdata data
} vtoken;
typedef struct
{
    vtoken *tk;
    size_t sz;
   size_t n;
} Vector;

所以这是一种可能的方式。数据类型的枚举,您可以避免使用typedefs,但如果使用mixed (例如: sum long,to double,to float等等),则必须使用它们,因为int + double不等于double+int;这也是一个原因,因为更容易看到联合来做这项工作。你让所有的算术规则原封不动。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42293192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档