私の行サイズは固定ですが、列サイズは常に変化し続けます。そのため、列レベルにポインターを使用することを考えています。しかし、Cでこの機能を使用する方法がわかりません。親切に助けてください。
int array[rows][columns]; //row size fixed but column size is not fixed.
各行が異なる数の列を持つことができる場合、一般的なアプローチはポインターの配列を宣言し、各行に対してその行の要素数を動的に割り当てることです。
int *array[ROWS];
array[i] = malloc(sizeof *array[i] * number_of_columns_for_row_i);
完了したら、各行を個別に解放する必要があることに注意してください。
for (i = 0; i < ROWS; i++)
free(array[i]);
すべての行の列数が同じで、その数が配列のインスタンスごとに変わる可能性がある場合は、いくつかの選択肢があります。C99 準拠のコンパイラを使用している場合は、実行時まで配列の次元が不明な可変長配列を使用できます。
int columns;
// get number of columns somehow
int array[ROWS][columns];
VLA は便利ですが、制限があります。のメンバーstruct
またはunion
型にすることはできず、宣言しstatic
たり、ファイル スコープで使用したりすることはできません。このアプローチの大きな利点は、完了時に何かを解放することを心配する必要がないことです。このアプローチの大きな欠点は、要求を満たすのに十分なメモリがない可能性があることです。変数に使用できるメモリ スペースauto
は、動的に割り当てられたオブジェクトのメモリに比べて、通常は非常に限られています。また、言語標準の最新リビジョン (C11) では VLA がオプションになっているため、今後のすべての実装で使用できるとは限りません。
または、次のように配列を動的に割り当てることもできます。
int (*array)[ROWS];
int columns;
// get number of columns somehow
array = malloc(sizeof *array * columns);
今回array
は、へのポインターの配列でint
はなく、 の配列へのポインターであることに注意してくださいint
。このアプローチの利点は、配列メモリが連続して割り当てられfree
、メモリの書き込みが書き込みと同じくらい簡単であることです。
free(array);
欠点は、配列が非常に大きい場合、または動的メモリ プールが非常に断片化されている場合、要求を満たすのに十分な大きさのメモリ チャンクを使用できない可能性があることです。
すべての行を連続して割り当てる必要がない場合は、各行を個別に割り当てる最初の方法を使用します。列数に同じ値を使用するだけです。
int *array[ROWS];
int columns;
// get number of columns
for (i = 0; i < ROWS; i++)
array[i] = malloc(sizeof *array[i] * columns);
ポインターの配列を宣言する必要があります。このような:
int *array[rows];
後で、必要に応じて、各行にメモリを割り当てます。これには、malloc または calloc 関数を使用できます。
for(int i=0; i<rows; i++){
array[i] = (int *) malloc(columns * sizeof(int));
}
この方法では、さまざまなサイズの行を持つこともできます。
配列の 1 つを除くすべての次元が固定されている場合 (これは、説明した状況です)、ポインターの配列の使用を避けることができます。行を として型定義しint[rows]
、次のように行の配列を作成できます。
typedef int row_t[rows];
row_t
これで、配列で構成される 2D 配列を次のように渡すことができます。
int total(row_t array[], int len) {
int res = 0;
for (int c = 0 ; c != len ; c++) {
for (int r = 0 ; r != rows ; r++) {
res += array[r][c];
}
}
return res;
}
int main() {
row_t *matrix = malloc(columns*sizeof(row_t));
for (int c = 0 ; c != columns ; c++) {
for (int r = 0 ; r != rows ; r++) {
matrix[r][c] = r*r+c*c;
}
}
printf("%d\n", total(matrix, columns));
free(matrix);
return 0;
}
配列次元では変数を使用できないため、ポインターへのポインターを使用します
int **array;
array = (int **)malloc(sizeof(int *) * rows);
for (int i = 0; i < rows; ++i) {
array[i] = (int *)malloc(sizeof(int) * columns);
for (int j = 0; j < columns; j++) {
array[i][j] = value;
}
}
もちろん、すべてを解放することを忘れないでください
int* の配列を使用してこれを行います。
int* array[row];
for (int i = 0; i < row; ++i)
array[i] = (int*)malloc(i * sizeof(int));
そして、静的であるかのようにデータにアクセスできます。
int val = array[myRow][myColumn];
割り当てたときと同じパターンでメモリを解放する必要があります。
13 年前から、C では配列の宣言で動的サイズが許可されています。これを可変長配列 VLA と呼びます。
本当に大きな配列がある場合、これによりスタックが爆発する可能性があります。malloc
しかし、2D 配列のすべての単純さを使用して、そのような野獣を割り当てることもできます。
size_t n = SOME_COMPLICATED_VALUE;
size_t m = ANOTHER_ONE;
double (*A)[n] = malloc(double[m][n]);