C动态地使用malloc和memcpy改变数组的大小

时间:2016-10-03 13:10:44

标签: c malloc dynamic-memory-allocation memcpy realloc

我想编写一个改变动态数组大小的函数,并允许用户立即填充它。我知道我应该使用“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在退出函数后不会自动释放。

然后可能是什么原因?

2 个答案:

答案 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提出了一种替代解决方案,通过将指针的地址传递给数组的第一个元素来解决这个问题。可以取消引用该指针并给出新分配的内存的地址值。通过这种方式,调用函数不是更明智的,因为每当调用函数访问数组时,它都会通过提供数组第一个元素地址的指针来实现。整齐。但我仍然认为我更愿意尽可能明确地传递指针 - 对我来说似乎更清楚。