C使用malloc和memcpy动态改变数组的大小
C dynamicaly changing size of array using malloc and memcpy
我想编写一个函数来更改动态数组的大小并允许用户立即填充它。我知道我应该使用 "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 被释放了...?但据我所知,分配的内存在退出函数后不会自动释放。
那可能是什么原因呢?
在函数内部,您正在将 malloc 分配的新内存分配给 dArray
,它具有块作用域。您需要将此指针传递回调用函数。 dArray
是你传入的指针的副本,当你return到调用函数时,原来的指针是不变的。你应该有一个像这样的函数调用:
ptr = ChangeDynamicArraySize(ptr, oldSize, newSize);
由于 dArray
是函数调用中传递的指针的副本,因此当您更改 *dArray
的值时,它在函数外部可见,因为您正在更改存储在原始指针和副本指向的内存位置。但是当你在函数内部重新分配 dArray
指针时,你只是说这个指针现在应该指向其他位置。 original还是指向原来的位置。
原始问题中的解决方案存在一个根本问题:当您将指向一段内存的指针传递给函数时,指针使用 malloc()
或 calloc()
或重新分配该内存realloc()
,新内存有了新地址。即使使用 realloc()
也是如此,因为旧位置可能没有足够的连续字节来分配请求的内存。原方案是在ChangeDynamicArraySize()
函数内部重新分配内存,然后修改这块内存的内容。但是在 returning 之后,调用函数不知道新内存在哪里。所以,你必须 return 一个指向新分配内存的指针给调用者。
@Diti 提出了一种替代解决方案,通过将指针的地址传递给数组的第一个元素来解决这个问题。这个指针可以被取消引用并赋予新分配的内存地址的值。这样,调用函数 none 就更聪明了,因为每当调用函数访问数组时,它都是通过提供数组第一个元素地址的指针来访问的。整洁的。但我仍然认为我更愿意尽可能明确地传递指针——这对我来说似乎更清楚。
在 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);
}
或者,您也可以 return 新 malloc
ed 数组的地址(使您的函数 return 这个 int*
而不是没有值)。
此外,为了获得良好实践,您可能需要 not cast the return of malloc
, and check whether it failed and changed ERRNO
(如果您使用 POSIX API)。
我想编写一个函数来更改动态数组的大小并允许用户立即填充它。我知道我应该使用 "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 被释放了...?但据我所知,分配的内存在退出函数后不会自动释放。
那可能是什么原因呢?
在函数内部,您正在将 malloc 分配的新内存分配给 dArray
,它具有块作用域。您需要将此指针传递回调用函数。 dArray
是你传入的指针的副本,当你return到调用函数时,原来的指针是不变的。你应该有一个像这样的函数调用:
ptr = ChangeDynamicArraySize(ptr, oldSize, newSize);
由于 dArray
是函数调用中传递的指针的副本,因此当您更改 *dArray
的值时,它在函数外部可见,因为您正在更改存储在原始指针和副本指向的内存位置。但是当你在函数内部重新分配 dArray
指针时,你只是说这个指针现在应该指向其他位置。 original还是指向原来的位置。
原始问题中的解决方案存在一个根本问题:当您将指向一段内存的指针传递给函数时,指针使用 malloc()
或 calloc()
或重新分配该内存realloc()
,新内存有了新地址。即使使用 realloc()
也是如此,因为旧位置可能没有足够的连续字节来分配请求的内存。原方案是在ChangeDynamicArraySize()
函数内部重新分配内存,然后修改这块内存的内容。但是在 returning 之后,调用函数不知道新内存在哪里。所以,你必须 return 一个指向新分配内存的指针给调用者。
@Diti 提出了一种替代解决方案,通过将指针的地址传递给数组的第一个元素来解决这个问题。这个指针可以被取消引用并赋予新分配的内存地址的值。这样,调用函数 none 就更聪明了,因为每当调用函数访问数组时,它都是通过提供数组第一个元素地址的指针来访问的。整洁的。但我仍然认为我更愿意尽可能明确地传递指针——这对我来说似乎更清楚。
在 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);
}
或者,您也可以 return 新 malloc
ed 数组的地址(使您的函数 return 这个 int*
而不是没有值)。
此外,为了获得良好实践,您可能需要 not cast the return of malloc
, and check whether it failed and changed ERRNO
(如果您使用 POSIX API)。