2016-10-03 123 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