我想编写一个改变动态数组大小的函数,并允许用户立即填充它。我知道我应该使用“realloc”(所以我做了,所以它有效......)但我的第一次尝试看起来像这样:
void ChangeDynamicArraySize(int* dArray, int oldSize, int newSize){
int* tempArray = (int*) malloc(sizeof(int) * oldSize);
CopyArray(tempArray, dArray, oldSize);
free(dArray);
dArray = (int*) malloc(sizeof(int) * newSize);
CopyArray(dArray, tempArray, oldSize);
for (int i = oldSize; i < newSize; i++){
scanf("%i", &dArray[i]);
}
PrintArray(dArray, newSize);
free(tempArray);
}
在函数体“PrintArray(dArray,newSize);”工作正确。 但是当从main()调用它时会得到如下结果: - 17891602 - 17891602 - 17891602 - 17891602
所以看起来dArray被释放了......?但正如我所知,分配的memmory在退出函数后不会自动释放。
然后可能是什么原因?
答案 0 :(得分:2)
在C中,函数参数在本地复制。您对值dArray
所做的任何更改都指向(*dArray
),但您对作为参数传递的dArray
的地址所做的任何更改都仅限于此功能,因为它是一个副本。
您可能希望传递数组的地址(主函数中的&array
,函数原型中的dArray**
),然后更改指针。
这样的事情:
void ChangeDynamicArraySize(int** dArray, int oldSize, int newSize){
int* tempArray = (int*) malloc(sizeof(int) * oldSize);
CopyArray(tempArray, *dArray, oldSize);
free(*dArray);
*dArray = (int*) malloc(sizeof(int) * newSize);
CopyArray(*dArray, tempArray, oldSize);
for (int i = oldSize; i < newSize; i++){
scanf("%i", dArray[i]);
}
PrintArray(*dArray, newSize);
free(tempArray);
}
或者,您也可以只返回新malloc
ed数组的地址(使您的函数返回此int*
而非没有值)。
此外,对于良好做法,您可能需要not cast the return of malloc
,并检查它是否失败以及changed ERRNO
(如果您使用POSIX API)。
答案 1 :(得分:1)
在函数内部,您将malloc分配的新内存分配给具有块范围的dArray
。您需要将此指针传递回调用函数。 dArray
是您传入的指针的副本,当您返回到调用函数时,原始指针不变。您应该有一个函数调用,如:
ptr = ChangeDynamicArraySize(ptr, oldSize, newSize);
由于dArray
是函数调用中传递的指针的副本,因此当您更改*dArray
的值时,THAT在函数外部可见,因为您正在更改存储在内存中的值原始指针和副本指向的位置。但是当你在函数内重新分配dArray
指针时,你只是说这个指针现在指向其他位置。原件仍然指向原始位置。
原始问题中的解决方案存在一个基本问题:当您将指向内存部分的指针传递给函数时,指针使用malloc()
或calloc()
或{{realloc()
重新分配该内存1}},新内存有一个新地址。即使使用realloc()
也是如此,因为旧位置可能没有足够的连续字节来分配请求的内存。原始解决方案在ChangeDynamicArraySize()
函数内重新分配内存,然后修改此内存的内容。但是在返回之后,调用函数不知道新内存在哪里。因此,您必须将指向新分配的内存的指针返回给调用者。
@Diti提出了一种替代解决方案,通过将指针的地址传递给数组的第一个元素来解决这个问题。可以取消引用该指针并给出新分配的内存的地址值。通过这种方式,调用函数不是更明智的,因为每当调用函数访问数组时,它都会通过提供数组第一个元素地址的指针来实现。整齐。但我仍然认为我更愿意尽可能明确地传递指针 - 对我来说似乎更清楚。