20

このint a[N][N] のような 2D 配列を割り当てると、連続したメモリ ブロックを割り当てます。

しかし、次のように動的に実行しようとすると:

int **a = malloc(rows * sizeof(int*));
for(int i = 0; i < rows; i++) 
   a[i] = malloc(cols * sizeof(int));

これにより、行内の要素間の単位ストライドが維持されますが、行間ではそうではない場合があります。

1つの解決策は2Dから1Dに変換することですが、それ以外にそれを行う別の方法はありますか?

4

7 に答える 7

22

コンパイル時に配列の次元がわかっている場合:

#define ROWS ...
#define COLS ...

int (*arr)[COLS] = malloc(sizeof *arr * ROWS);
if (arr) 
{
  // do stuff with arr[i][j]
  free(arr);
}

コンパイル時に配列の次元がわからず、可変長配列をサポートする C99 コンパイラまたは C2011 コンパイラを使用している場合:

size_t rows, cols;
// assign rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
  // do stuff with arr[i][j]
  free(arr);
}

コンパイル時に配列の次元がわからず、可変長配列をサポートする C99 コンパイラまたは C2011 コンパイラを使用していない場合:

size_t rows, cols;
// assign rows and cols
int *arr = malloc(sizeof *arr * rows * cols);
{
  // do stuff with arr[i * rows + j]
  free(arr);
}
于 2012-11-23T20:50:36.860 に答える
9

実際、n 次元配列 (スタックに割り当てられている) は、実際には単なる 1 次元ベクトルです。複数のインデックスは単なる構文糖衣です。ただし、アクセサ関数を記述して、必要なものをエミュレートできます。

int index_array(int *arr, size_t width, int x, int y)
{
    return arr[x * width + y];
}

const size_t width = 3;
const size_t height = 2;
int *arr = malloc(width * height * sizeof(*arr));

// ... fill it with values, then access it:

int arr_1_1 = index_array(arr, width, 1, 1);

ただし、C99 をサポートしている場合は、配列へのポインターを宣言することが可能であり、シンタックス シュガーを使用することもできます。

int (*arr)[width] = malloc(sizeof((*arr) * height);
arr[x][y] = 42;
于 2012-11-23T19:53:01.730 に答える
3

動的に割り当てられたメモリは、ストライドでアクセスすることにより、任意の次元の配列として扱うことができます。

int * a = malloc(sizeof(int) * N1 * N2 * N3);  // think "int[N1][N2][N3]"

a[i * N2 * N3 + j * N3 + k] = 10;              // like "a[i, j, k]"
于 2012-11-23T20:04:22.367 に答える
2

フォーマット不足や間違いをお詫びしますが、これは携帯電話からのものです。

また、src アドレスとして int** 変数を使用して fwrite() を使用して出力しようとしたストライドにも遭遇しました。

1 つの解決策は、2 つの malloc() 呼び出しを利用することでした。

#define HEIGHT 16
#define WIDTH 16

.
.
.
//allocate
int **data = malloc(HEIGHT * sizeof(int **));
int *realdata = malloc(HEIGHT * WIDTH * sizeof(int));

//manually index
for (int i = 0; i < HEIGHT; i++)
    data[i] = &realdata[i * WIDTH];

//populate
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
    for (int j = 0; j < WIDTH; j++)
        data[i][j] = idx++;

//select
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
{
    for (int j = 0; j < WIDTH; j++)
        printf("%i, ", data[i][j]);
    printf("/n");
}

//deallocate
.
.
.
于 2014-04-09T00:45:01.513 に答える
1

配列を型定義して(頭を悩ませるために)、次のようなことを行うことができます。

#include <stdlib.h>
#define N 10
typedef int A[N][N];
int main () {
  A a; // on the stack
  a[0][0]=1;
  A *b=(A*)malloc (sizeof(A)); // on the heap
  (*b)[0][0]=1;
}
于 2012-11-23T20:02:02.223 に答える
1

最善の方法は、配列へのポインターを割り当てることです。

int (*a)[cols] = malloc(rows * sizeof *a);
if (a == NULL) {
    // alloc failure, handle or exit
}

for(int i = 0; i < rows; ++i) {
    for(int j = 0; j < cols; ++j) {
        a[i][j] = i+j;
    }
}

コンパイラが可変長配列をサポートしていない場合colsは、定数式の場合にのみ機能します (ただし、とにかくコンパイラをアップグレードする必要があります)。

于 2012-11-23T20:14:06.987 に答える