2016-10-03 101 views
1

我想写一个函数来改变动态数组的大小,并允许用户一次填充它。我知道,我应该使用的“realloc的”做(所以我做,所以它的工作原理...),但我第一次尝试是这样的:C动态改变使用malloc和memcpy的数组大小的大小

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,新尺寸) ;”工作正确。 但是从主称为()时,它给出的结果,如: - 17891602 - 17891602 - 17891602 - 17891602

所以看起来dArray被放了出来...?但据我所知分配的内存不会在退出函数后自动释放。

那么可能是什么原因?

+0

A,而CopyArray就是我的memcpy版本() – WJuz

+3

'dArray'是按值传递的,你只是在改变它的本地副本。 – deniss

回答

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版数组的地址(让你的函数返回此int*而不是没有价值)。

此外,对于最佳实践,您可能需要not cast the return of malloc,并检查它是否失败,并且changed ERRNO(如果您使用POSIX API)。

+0

A,好的...我明白了,谢谢:) – WJuz

+0

我试过这个,但是scanf(“%i”,dArray [i])上升违反了写入位置0xcccccccc。 – WJuz

+0

但那一个:scanf(“%i”,&(* dArray)[i])似乎很好;)现在它工作。 – WJuz

1

函数内部分配由malloc分配的新内存到dArray,它具有块范围。您需要将此指针传递回调用函数。 dArray是您传入的指针的副本,当您返回到调用函数时,原始指针保持不变。你应该有一个函数调用,比如:

ptr = ChangeDynamicArraySize(ptr, oldSize, newSize); 

由于dArray是在函数调用中传递的指针的拷贝,当你改变*dArray的价值,那就是功能的外部可见的,因为你正在改变值存储在由原始指针和副本指向的存储器位置。但是当你在函数内重新指定dArray指针时,你只是说这个指针现在应该指向其他位置。原件仍指向原始位置。

在原来的问题解决方案从根本问题的困扰:当你传递一个指针的内存功能的部分,并且指针重新分配内存使用malloc()calloc()realloc(),新的内存有一个新的地址。即使使用realloc()也是如此,因为旧位置可能没有足够的连续字节来分配请求的内存。原来的解决方案重新分配ChangeDynamicArraySize()函数内的内存,然后修改此内存的内容。但返回后,调用函数不知道新内存在哪里。所以,你必须返回一个指向调用者新分配的内存的指针。

@Diti提出了另一种解决方案,通过将指针的地址传递给数组的第一个元素来解决此问题。该指针可以被解引用,并给出新分配的内存地址的值。通过这种方式,调用函数并不明智,因为无论调用函数何时访问数组,都会通过提供数组第一个元素地址的指针来实现。整齐。但我仍然认为我更愿意在任何可能的情况下明确地通过指针 - 这对我来说似乎更加清楚。

+0

Hm,dArray是一个指针,所以我认为在块中完成的操作也会影响它外面的指针 - 比如改变变量的值... – WJuz

+1

没有。在函数内部,您只需使用副本。如果在函数中更改'* dArray',则THAT将在函数之外可见,因为您正在更改原始指针和副本所指向的内存中存储的值。但是如果你在函数内部重新指定指针,你只是说这个指针是一个其他指针的副本,现在应该指向别的地方。 –

+0

好吧,现在我明白如果我在我的ChangeSize函数体中调用realloc(),那么效果在main()中也是可见的,因为realloc()指向由MainPointer和ChangeSizePointer指向的内存块。希望我是对的......它只是改变它的大小,而不是位置。 – WJuz