C结构的动态向量

时间:2016-03-06 15:30:23

标签: c vector dynamic struct

我有一个动态矢量的结构:

typedef struct {
    TElement *data;
    int len;
}Vector;

和2个函数,一个用于初始化向量,另一个用于追加元素:

Vector *initVector()
{
    Vector *v;
    v = malloc(sizeof(TElement));
    v->len = 0;
    return v;
}
void append(Vector *v, TElement element)
{
    v = (Vector *)realloc(v, (v->len + 1) * sizeof(TElement));
    v->data[v->len++] = element;
}

当我尝试追加一个元素时,程序崩溃了,我不知道为什么,有什么想法?

4 个答案:

答案 0 :(得分:1)

在您的代码中,v的类型为Vector *,并且您正在分配大小为TElement的内存,这是错误的。

更改

v = malloc(sizeof(TElement));

v = malloc(sizeof*v);

那就是说,

  • malloc()失败的情况下,通过检查返回的指针是否为NULL来检查malloc()是否成功,以避免任何可能的UB。

  • p = realloc(p,...)样式非常糟糕,因为如果realloc()失败,你也会失去实际的指针。在临时指针中捕获realloc()的返回值,检查NULL是否成功,然后分配回原始指针。

答案 1 :(得分:0)

  • 在功能initVector()中,分配sizeof(Vector)而不是sizeof(TElement)
  • 在功能append中,修改v->data而不是v并删除不需要且有害的演员。

更正后的代码:

Vector *initVector()
{
    Vector *v;
    v = malloc(sizeof(*v));
    v->len = 0;
    return v;
}
void append(Vector *v, TElement element)
{
    v->data = realloc(v->data, (v->len + 1) * sizeof(TElement));
    v->data[v->len++] = element;
}

答案 2 :(得分:0)

在你的initVector中,你应该为一个Vector预留空间。此外,必须v->data设置为NULL,或者设置有效的分配指针,否则您的代码将具有未定义的行为。

Vector *initVector() {
    Vector *v;
    v = malloc(sizeof Vector);
    if (! v) {
        /* error: malloc failed */
    }
    v->data = 0;
    v->len = 0;
    return v;
}

append中,您应该调整data指向的区域的大小,而不是Vector分配本身:

void append(Vector *v, TElement element) {
    TElement *new_p = realloc(v->data, (v->len + 1) * sizeof(TElement));

    if (!new_p) {
        /* error: malloc failed */
    }
    v->data = new_p;
    v->data[v->len++] = element;
}

检查malloc的返回值也是个好主意;如果不是这样,那么在打印出合理的消息之后中止而不是在难以理解的SIGSEGV崩溃是有道理的。

此外,每次向量增加一个项目意味着项目插入在具有n项目的容器上具有O(n)时间复杂度。最好以几何级数分配空间(例如,当您需要调整分配大小时,然后将分配扩展1.5或2,而不是按常量),并从较大的最小分配8开始或者16项。

答案 3 :(得分:0)

您需要的是以下

Vector *initVector()
{
    Vector *v = malloc( sizeof( Vector ) );
                                 ^^^^^^
    if ( v != NULL )
    {
        v->len = 0;
        v->data = NULL;
        ^^^^^^^^^^^^^^^
    }

    return v;
}

void append( Vector *v, TElement element )
{
    TElement *tmp = realloc( v->data, ( v->len + 1 ) * sizeof( TElement ) );
                             ^^^^^^^^    
    if ( tmp != NULL )
    {
        v->data = tmp;
        v->data[len++] = element;
    }
}

最后一个函数的返回类型可以从void更改为int,以报告是否附加了新元素。例如

int append( Vector *v, TElement element )
{
    int success;

    TElement *tmp = realloc( v->data, ( v->len + 1 ) * sizeof( TElement ) );
                             ^^^^^^^^    
    if ( ( success = tmp != NULL ) )
    {
        v->data = tmp;
        v->data[len++] = element;
    }

    return success;
}