[英]Reallocating array within a struct
我正在為學校編寫一個程序,要求我們創建一個結構,該結構具有一個整數數組以及兩個整數變量(容量和大小),您可以猜出它的大小和容量。 當我需要為數組重新分配空間時,麻煩就開始了(教授不希望我們使用realloc
)。 這是代碼...
#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
#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;
}
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.