c - 在结构中重新分配数组

标签 c arrays struct

我正在为学校编写一个程序,该程序要求我们创建一个结构,该结构具有一个整数数组以及两个整数变量 capacity 和 size,它们跟踪(您猜对了)数组的大小和容量。当我需要为数组重新分配空间时,问题就开始了(教授不希望我们使用 realloc)。这是代码...

dynamicArray.h文件

#ifndef DYNAMIC_ARRAY_INCLUDED
#define DYNAMIC_ARRAY_INCLUDED 1

#ifndef __TYPE
#define __TYPE
# define TYPE int
# endif

typedef struct DynArr DynArr;

/* Dynamic Array Functions */
void initDynArr(DynArr *v, int capacity);
DynArr *newDynArr(int cap);

void freeDynArr(DynArr *v);
void deleteDynArr(DynArr *v);

int sizeDynArr(DynArr *v);

void addDynArr(DynArr *v, TYPE val);    

#endif

dynamicArray.c文件

#include <assert.h>
#include <stdlib.h>
#include "dynArray.h"

struct DynArr
{
    TYPE *data;     /* pointer to the data array */
    int size;       /* Number of elements in the array */
    int capacity;   /* capacity ofthe array */
};

void printArray(DynArr *v)
{
    for (int i = 0; i < v->size; i++)
    {
        printf("%d, ", v->data[i]);

    }
    printf("\n");
}

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    /*check that v is initialized*/
    assert(v!=0);

    /*create temporary array with new capacity*/
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; i++)
    {
        tmp->data[i] = v->data[i];
        tmp->size++;
    }

    /*delete contents of old array*/
    deleteDynArr(v);

    /*assign address of new array to v*/
    v = tmp;
}

void deleteDynArr(DynArr *v)
{
    freeDynArr(v);
    free(v);
}

void freeDynArr(DynArr *v)
{
    if(v->data != 0)
    {
        free(v->data);  /* free the space on the heap */
        v->data = 0;    /* make it point to null */
    }
    v->size = 0;
    v->capacity = 0;
}

DynArr *newDynArr(int cap)
{
    assert(cap > 0);
    DynArr *r = (DynArr *)malloc(sizeof( DynArr));
    assert(r != 0);
    initDynArr(r,cap);
    return r;
}

void initDynArr(DynArr *v, int capacity)
{
    assert(capacity > 0);
    assert(v!= 0);
    v->data = (TYPE *) malloc(sizeof(TYPE) * capacity);
    assert(v->data != 0);
    v->size = 0;
    v->capacity = capacity;
}

main.c 文件

#include <stdio.h>
#include <stdlib.h>
#include "dynArray.h"

#define TYPE int

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

    DynArr *dyn;
    dyn = newDynArr(2);

    printf("\n\nTesting addDynArr...\n");
    addDynArr(dyn, 3);
    printArray(dyn);
    addDynArr(dyn, 4);
    printArray(dyn);
    addDynArr(dyn, 10);
    printArray(dyn);
    addDynArr(dyn, 5);
    printArray(dyn);
    addDynArr(dyn, 6);
    printArray(dyn);

    return 0;
}

我删减了代码(我知道它看起来可能不像)所以这是我的问题的要点。我在 dynamicArray.c 文件中遇到段错误。具体在这个函数中

void addDynArr(DynArr *v, TYPE val)
{
    /* checking that v has been initialized*/
    assert(v != 0);

    /*check if capacity is reached and increase if necessary*/
    if(v->size >= v->capacity)
    {
        _dynArrSetCapacity(v, (v->capacity) * 2);
    }

    /*add new value to array*/
    v->data[v->size] = val;

    /*increment size of array*/
    v->size++;

}

在 v->data[v->size] = val;线。我确实注意到,当我在前面提到的代码行之前检查 v->size 的值时,它会返回垃圾值。这让我觉得,当我将 v 传递给 _dynArrSetCapacity 函数时,它是按值而不是按引用传递的,但我看不出这是怎么可能的。任何帮助将不胜感激。

最佳答案

问题出在 void _dynArrSetCapacity(DynArr *v, int newCap) 中。您可能需要检查所有涉及内存重新分配的函数是否存在类似问题。

从技术上讲,C 中没有引用,因此每个参数都是按值传递或复制的。但是你复制的是指针,而不是整个 DynArray 对象。这意味着当您执行 deleteDynArray() 时,内存会像您预期的那样消失,但是当您到达 v = tmp; 时,它会更改本地 v(本地副本)而不是传入的 v。然后当您返回 v->data[v->size] = val;,您可能正在访问尚未分配的内存,从而导致错误。

最快的解决方法(IMO 虽然不是最好的)是对任何像这样进行释放的函数使用双指针而不是单个指针:

void _dynArrSetCapacity(DynArr **v, int newCap)
{
    DynArr *tmp = newDynArr(newCap);

    /*copy contents of v to new array*/
    ......
    /*delete contents of old array*/
    deleteDynArr(*v);

    /*assign address of new array to v*/
    *v = tmp;
    (*v)->size = newCap;
}

还有一个替代方案,我认为这可能更好。您不必重新分配整个对象。只是 DynArray 对象中包含所有相关对象的内存块:TYPE *data

void _dynArrSetCapacity(DynArr *v, int newCap)
{
    TYPE *tmp = (TYPE*)malloc(sizeof(Type) * newCap);

    /*copy contents of v to new array*/
    for (int i = 0; i < v->size; ++i)
        tmp[i] = v->data[i];
    /*delete contents of old array*/
    free(v->data);

    /*assign address of new array to v*/
    v->data = tmp;
    v->size = newCap;
}

关于c - 在结构中重新分配数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36512408/

相关文章:

c++ - C/C++ 对结构体中的结构体数组进行 qsort

python - 何时使用 .shape 何时使用 .reshape?

python - 从 np.float64 转换为 np.float32 完全改变了一些数字的值

c - C编程:读取文件并存储在struct数组中

C UART 始终不工作

c - 函数返回零

c++ - 为什么有不同类型的指针?

arrays - 将所有工作表数据打印到用户表单文本框中

Matlab对象实例更新

c++ - 通过网络发送结构