11

3 つの float の配列へのポインターの配列を作成したいと考えています。これを行う正しい方法は何ですか?

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つの浮動小数点数を割り当てたので、各浮動小数点数を解放し、次に3つの浮動小数点配列を解放し、次に配列全体を解放しますか?? ?

4

3 に答える 3

2

3 つの float の配列へのポインターの配列を作成したいと考えています。これを行う正しい方法は何ですか?

なぜあなたは欲しいの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 の配列にメモリを割り当てると、次のようになります。

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

次に、配列で free を呼び出すだけでよく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);

free次に、次のようにfor everymallocを実行する必要があります。

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

ここで学ぶべき教訓は、配列をまとめて動的に割り当てることを避けることです。std::vectorまたはスタック割り当て配列のいずれかに固執します。

于 2013-06-10T21:47:55.610 に答える
2

一般的な規則として、for を呼び出すたびに、malloc()または返されたポインタcalloc()に対して呼び出しを行う必要がありfree()ます。

コンパイル時に既知のサイズの 2 次元配列が必要な場合は、2 次元配列を使用してください。float val[5][3]完全に有効です。

2 次元配列が必要で、コンパイル時にそのサイズがわからない場合は、標準の単一次元 calloc() と適切な 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;
}

もちろん、定義を適切な変数に置き換えます。

そうすることで、次のことを行います。

  • コストのかかる割り当てと解放を節約する
  • 断片化された記憶が少ない
  • 可能な再割り当て呼び出しを簡素化する
  • [x][y] と [y][x] の反復キャッシュの問題が発生することなく、データがより適切にキャッシュされ、アクセスされるようにします。
于 2013-06-10T21:57:11.883 に答える