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 新 malloced 数组的地址(使您的函数 return 这个 int* 而不是没有值)。

此外,为了获得良好实践,您可能需要 not cast the return of malloc, and check whether it failed and changed ERRNO(如果您使用 POSIX API)。