How do I work with dynamic multi-dimensional array

2018-12-31 08:47发布

Does someone know how I can use dynamically allocated multi-dimensional arrays using C? Is that possible?

标签: c arrays dynamic
9条回答
闭嘴吧你
2楼-- · 2018-12-31 09:14

Why, colleagues, nobody revealed the fact that no exact solution exists in the realm of C? but only in C++ (by exact I mean that above and other site's solutions differ from true C-multidimentional arrays with: aditional entities and so additional memory, etc).

In C++ you must implement (just several lines of code):

typedef double T;
class Matrix2D
{
public:
    Matrix2D(int, int);
   ~Matrix2D();
    T* operator[](int);
private:
    T* const  memory;
    const int rows;
    const int cols;
};

Matrix2D::Matrix2D(int r, int c) : rows(r), cols(c), memory(new T[r*c]) {}
Matrix2D::~Matrix2D() { delete[]  memory; }
T* Matrix2D::operator[](int row) {  return memory + cols*row;}

That's all for those who use code like this: a[i][j].

But for exact similarity with C-multidimensional arrays that class (Matrix2D) lacks double-pointer arithmetics, to be used like this: (*(a+i))[j]. That is not difficult: implement inner clsss "doublePointer" with arithmetics and dereference operators. But I'd rather implemented sort of iterator for such purposes (to step from row to row).

More than 2 dimensions? You just need inner classes that implement corresponding operator[]...[] of (n-1)-dimension. Alas, routine..

查看更多
泛滥B
3楼-- · 2018-12-31 09:19

Since C99, 13 years now, C has 2D arrays with dynamical bounds. If you want to avoid that such beast are allocated on the stack (which you should), you can allocate them easily in one go as the following

double (*A)[n] = malloc(sizeof(double[n][n]));

and that's it. You can then easily use it as you are used for 2D arrays with something like A[i][j]. And don't forget that one at the end

free(A);

Randy Meyers wrote series of articles explaining variable length arrays (VLAs).

查看更多
与君花间醉酒
4楼-- · 2018-12-31 09:26

If you know the number of columns at compile time, it's pretty simple:

#define COLS ...
...
size_t rows;
// get number of rows
T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T

You can treat ap like any 2D array:

ap[i][j] = x;

When you're done you deallocate it as

free(ap);

If you don't know the number of columns at compile time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, it's still pretty simple:

size_t rows;
size_t cols;
// get rows and cols
T (*ap)[cols] = malloc(sizeof *ap * rows);
...
ap[i][j] = x;
...
free(ap);

If you don't know the number of columns at compile time and you're working with a version of C that doesn't support variable-length arrays, then you'll need to do something different. If you need all of the elements to be allocated in a contiguous chunk (like a regular array), then you can allocate the memory as a 1D array, and compute a 1D offset:

size_t rows, cols;
// get rows and columns
T *ap = malloc(sizeof *ap * rows * cols);
...
ap[i * rows + j] = x;
...
free(ap);

If you don't need the memory to be contiguous, you can follow a two-step allocation method:

size_t rows, cols;
// get rows and cols
T **ap = malloc(sizeof *ap * rows);
if (ap)
{
  size_t i = 0;
  for (i = 0; i < cols; i++)
  {
    ap[i] = malloc(sizeof *ap[i] * cols);
  }
}

ap[i][j] = x;

Since allocation was a two-step process, deallocation also needs to be a two-step process:

for (i = 0; i < cols; i++)
  free(ap[i]);
free(ap);
查看更多
看风景的人
5楼-- · 2018-12-31 09:28

There's no way to allocate the whole thing in one go. Instead, create an array of pointers, then, for each pointer, create the memory for it. For example:

int** array;
array = (int**)malloc(sizeof(int*) * 50);
for(int i = 0; i < 50; i++)
    array[i] = (int*)malloc(sizeof(int) * 50);

Of course, you can also declare the array as int* array[50] and skip the first malloc, but the second set is needed in order to dynamically allocate the required storage.

It is possible to hack a way to allocate it in a single step, but it would require a custom lookup function, but writing that in such a way that it will always work can be annoying. An example could be L(arr,x,y,max_x) arr[(y)*(max_x) + (x)], then malloc a block of 50*50 ints or whatever and access using that L macro, e.g.

#define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)]

int dim_x = 50;
int dim_y = 50;

int* array = malloc(dim_x*dim_y*sizeof(int));

int foo = L(array, 4, 6, dim_x);

But that's much nastier unless you know the effects of what you're doing with the preprocessor macro.

查看更多
时光乱了年华
6楼-- · 2018-12-31 09:30
int rows, columns;
/* initialize rows and columns to the desired value */

    arr = (int**)malloc(rows*sizeof(int*));
        for(i=0;i<rows;i++)
        {
            arr[i] = (int*)malloc(cols*sizeof(int));
        }
查看更多
皆成旧梦
7楼-- · 2018-12-31 09:35

malloc will do.

 int rows = 20;
 int cols = 20;
 int *array;

  array = malloc(rows * cols * sizeof(int));

Refer the below article for help:-

http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf

查看更多
登录 后发表回答