简体   繁体   English

在C中调整结构中数组的大小

[英]Resizing an array within a struct in C

I am having problems wrapping my brain around proper use of pointers with arrays in C. 我在用C语言中的数组正确使用指针方面遇到问题。

The project I am working on is building a simple Dynamic Array and the functions to go along with it. 我正在从事的项目正在构建一个简单的动态数组及其功能。 However I do not seem to be able to find the correct syntax/functions to update the array size dynamically. 但是,我似乎无法找到正确的语法/函数来动态更新数组大小。 Here is the relevent code: 这是相关的代码:

Array Creation: 数组创建:

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


void initDArray(DArray *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;
}


DArray* createDArray(int cap)
{
    assert(cap > 0);
    DArray *r = (DArray *)malloc(sizeof( DArray));
    assert(r != 0);
    initDArray(r,cap);
    return r;
}

And the problem bit, in its current non-working form: 和问题位,以目前的无效形式:

    void _DArraySetCapacity(DArray *v, int newCap)
{

    TYPE * newptr = createDArray(newCap);
    newptr = (TYPE *) malloc(sizeof(TYPE) * newCap);
    v->capacity = newCap;
    v->data = newptr;

}

My method being to create a temporary pointer with increased memory allocation then copy the existing date to it and point the data pointer at the new location. 我的方法是创建一个增加内存分配的临时指针,然后将现有日期复制到该指针,然后将数据指针指向新位置。 I suspect I may be looking at the issue in entirely the wrong way. 我怀疑我可能以完全错误的方式看待这个问题。

Any help tips or pointers (pun intended) would be appreciated. 任何帮助提示或指针(双关语的意图)将不胜感激。 Thanks in advance. 提前致谢。

What about using realloc ? 那使用realloc呢?

The C library function void *realloc(void *ptr, size_t size) attempts to resize the memory block pointed to by ptr that was previously allocated with a call to malloc or calloc. C库函数void * realloc(void * ptr,size_t size)尝试调整ptr指向的内存块的大小,该内存块先前是通过调用malloc或calloc分配的。

Fortunately, you don't need to move memory around yourself: realloc does that for you. 幸运的是,您不需要在自己周围移动内存: realloc会为您完成此操作。

In your case a typical usage would be: 在您的情况下,典型用法是:

v->capacity = newCap;
v->data = realloc(v->data, newCap * sizeof *v->data); /* same as sizeof(TYPE) */

Note that you don't have to (and shouldn't) cast the result of malloc/calloc or realloc. 请注意,您不必(也不应该)强制转换malloc / calloc或realloc的结果。

Use realloc() ! 使用realloc()

See this question and answer to better understand realloc and how its used. 请参阅此问题和答案,以更好地了解realloc及其用法。

Dynamic generic arrays in C are unexpectedly easy. C语言中的动态泛型数组异常简单。

Appending/inserting elements: 追加/插入元素:

size_t size = 0, count = 0;
mytype_t *items; // array of mytype_t

mytype_t foo1, foo2, foo3;

carray_grow(items, size, count += 1); // grow to 1
items[0] = foo3;

carray_grow(items, size, count += 2); // grow to 3
carray_insert(items, count, 0, 2); // shift 2 up at 0
items[0] = foo1;
items[1] = foo2;

Removing elements: 删除元素:

carray_remove(items, count, 0, 2); // remove 2 at 0
carray_grow(items, size, count -= 2); // shrink to 1

Free it completely? 完全释放它?

carray_grow(items, size, count = 0);

Backend (few defines and single function ahead): 后端(很少定义和前面有单个功能):

int carray_xgrow(void **datap, size_t *sizep, size_t esize, size_t count);
// 0 or -1/errno(realloc)

#define carray_grow(array, size, count) carray_xgrow((void **)&(array), &(size), sizeof((array)[0]), count)
// 0 or -1/errno(realloc)

#define carray_move(array, from, to, n) memmove(&(array)[to], &(array)[from], sizeof((array)[0]) * (n))
#define carray_insert(array, count, i, n) carray_move(array, i, (i)+(n), (count)-(i)-(n))
#define carray_remove(array, count, i, n) carray_move(array, (i)+(n), i, (count)-(i)-(n))

int
carray_xgrow(void **datap, size_t *sizep, size_t esize, size_t count)
{
    assert(datap != NULL);
    assert(sizep != NULL);
    assert(esize > 0);

    size_t size = *sizep;
    {
        size_t cap = size / esize;

        if (cap >= count * 2) // regrow at 1/2
            cap = 0;

        while (cap < count) // grow by 3/2
            cap = (cap < 2) ? (cap + 1) : (cap * 3 / 2);

        size = cap * esize;
    }

    if (size != *sizep) {
        if (size) {
            void *data = realloc(*datap, size);
            if (data == NULL) return -1;
            *datap = data;
            *sizep = size;
        }
        else {
            free(*datap);
            *datap = NULL;
            *sizep = 0;
        }
    }
    return 0;
}

(Note size in bytes, but cap and count in elements.) (注意大小以字节为单位,但上限和计数以元素为单位。)

EDIT: removed minor dependencies 编辑:删除次要依赖项

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

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