簡體   English   中英

正確的方法來分配和釋放指向數組的指針

[英]Correct way to allocate and free arrays of pointers to arrays

我想創建一個指向3個浮點數組的指針數組。 這樣做的正確方法是什么?

float *array1[SIZE]; // I think it is automatically allocated
// OR
float **array1 = calloc(SIZE, sizeof(float*));
free(array1);

for (int i = 0; i < SIZE; i++) {
    array1[i] = (float[]){0,0,0};
    // OR
    array1[i] = calloc(3, sizeof(float));
}

那么我將如何釋放數據呢? 我很確定只有free(array1); 不會工作,所以我會釋放數組中的每個指針然后釋放數組,或者因為我分配了三個浮點數,我會釋放每個浮點數,然后每個3浮點數組,然后整個數組???

如果你在編譯時知道數組大小(如果你知道,如果SIZE是編譯時常量),你應該只聲明一個二維數組。 你根本不需要釋放它(也絕不能)。

float array1[SIZE][3];

只有在編譯時不知道維度時,才需要使用calloc並創建指針數組。 在這種情況下,每次調用calloc都應該有一個free的調用。 並且由於在釋放數組后無法使用數組,因此在釋放array1之前需要釋放行數組。

float **array1 = calloc(nrows, sizeof (float *));
for (int i=0; i < nrows; i++)
    array1[i] = calloc(3, sizeof(float));
// Use it...

// Now free it
for (int i=0; i < nrows; i++)
    free(array1[i]);
free(array1);

編輯:如果您不重新排列指針(例如,對行進行排序),您只需使用一個calloc (以及之后的一次free調用)即可完成所有這些操作:

float (*array1)[3] = calloc(3*nrows, sizeof (float));

這是因為數在編譯時是已知的,這就是所有指針算術需要知道的。 然后你可以編寫像array1[i][j]這樣的東西,你仍然可以傳遞array1[i] ,好像它是一個指向行的真實指針。 C很棒,利用它!

我想創建一個指向3個浮點數組的指針數組。 這樣做的正確方法是什么?

為什么要一個array of pointers to arrays array of arrays不足夠嗎? (請記住,數組已經是指針式的,它們不是通過值傳遞的,而是當數組作為參數傳遞給函數時傳遞第一個元素的地址)。

// stack allocation, no need to free
float array[SIZE][3]; 

for (int i = 0; i < SIZE; i++) {
    // do something with array[i][0], array[i][1], array[i][2]
}

那么我將如何釋放數據呢?

在這種情況下,您不會,因為數據是堆棧分配的(一旦超出范圍將自動清理)。 請記住,經驗法則是,對於您所做的每個內存分配,都需要相應的空閑。 因此,如果為浮點數組分配內存,就像在

float* arr = malloc(sizeof(float) * 3); // array of 3 floats

然后你只需要在malloc'd的數組上調用malloc'd ,而不需要釋放單獨的浮點數。 如果您執行嵌套分配,請執行

// array of length SIZE, consisting of float pointers
float** arr = malloc(sizeof(float*) * SIZE);

// allocate the array of 3 floats at each index
for (int i = 0; i < SIZE; i++) 
    arr[i] = malloc(sizeof(float) * 3);

然后你需要為每個malloc執行一個free的,就像在

// free the individual arrays
for (int i = 0; i < SIZE; i++)
    free(arr[i]);
// free the array of arrays
free(arr);

這里要取消的教訓是避免將數組全部動態分配。 堅持使用std::vector或堆棧分配的數組。

一般規則是, 每次調用malloc()calloc() ,都需要對返回的指針執行free()調用

如果你想要一個編譯時已知大小的二維數組,只需使用二維數組! float val[5][3]完全有效。

如果你想要一個二維數組並且在編譯期間你不知道它的大小,你很可能想要使用一個標准的,單個的dieca()和一個合適的getter。

#define ARR_COLUMNS 10
#define ARR_ROWS 10
float* arr = calloc (ARR_COLUMNS * ARR_ROWS, sizeof(float));

int get(float* arr, int x, int y) {
  if (x<0 || x>= ARR_COLUMNS) return 0;
  if (y<0 || y>= ARR_ROWS) return 0;
  return arr[ARR_COLUMNS*y+x];
}

void set (int* arr, int x, int y, float val) {
  if (x<0 || x>= ARR_COLUMNS) return;
  if (y<0 || y>= ARR_ROWS) return;
  arr[ARR_COLUMNS*y+x] = val;
}

當然用適當的變量替換定義。

通過這樣做,您將:

  • 節省自己昂貴的分配和釋放
  • 內存碎片少
  • 簡化您可能的realloc調用
  • 確保數據更好地緩存並在沒有常見的[x] [y] vs [y] [x]迭代緩存問題的情況下訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM