18

i want to allocate a matrix.

is this the only option:

int** mat = (int**)malloc(rows * sizeof(int*))

for (int index=0;index<row;++index)
{
    mat[index] = (int*)malloc(col * sizeof(int));
}
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Idan
  • 5,717
  • 10
  • 47
  • 84

6 Answers6

50

Well, you didn't give us a complete implementation. I assume that you meant.

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

Here's another option:

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

Then, you simulate the matrix using

int offset = i * cols + j;
// now mat[offset] corresponds to m(i, j)

for row-major ordering and

int offset = i + rows * j;
// not mat[offset] corresponds to m(i, j)

for column-major ordering.

One of these two options is actually the preferred way of handling a matrix in C. This is because now the matrix will be stored contiguously in memory and you benefit from locality of reference. Basically, the CPU cache will a lot happier with you.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 2
    if your compiler supports variable-length arrays or if `cols` is a compile-time constant, you don't even need to compute the offsets yourself; if you use `int (*mat)[cols] = malloc(rows * sizeof *mat)`, you can access the elements via `mat[i][j]` and still use a contiguous block of memory – Christoph Jan 24 '10 at 20:52
  • 3
    Even ignoring performance, a single allocation is also preferable because it's simpler. There are fewer things to deallocate later, and there's no need to deal with partial allocation failures. – jamesdlin Jan 24 '10 at 21:11
  • 1
    Wouldn't this be a problem if each malloc created discontinuous memory blocks, making their addresses not serial? For example, the first malloc could return the pointer 0x635 and the other mallocs could return pointers 0xA279, 0xB7DD, etc.. If this happens a simple calculation such as stated above would not work. – Bruno Philipe Nov 29 '13 at 00:16
7

The other answers already covered these, but for completeness, the comp.lang.c FAQ has a relevant entry:

How can I dynamically allocate a multidimensional array?

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • http://c-faq.com is an extraordinary source of such things like C hacks (for C++ http://www.parashift.com/c++-faq/) – 42n4 Dec 08 '14 at 18:54
5

what you can do is

int (*mat)[col];
mat=(int (*)[col])malloc(sizeof(*mat)*row);

and then use this new matrix as mat[i][j]

abhay jain
  • 146
  • 1
  • 8
3

You may also use calloc, which will additionally zero initialize the matrix for you. The signature is slightly different:

int *mat = (int *)calloc(rows * cols, sizeof(int));
Stéphan Kochen
  • 19,513
  • 9
  • 61
  • 50
2

How about just:

int* mat = malloc(rows * columns * sizeof(int));
Ana Betts
  • 73,868
  • 16
  • 141
  • 209
0

You can collapse it to one call to malloc, but if you want to use a 2d array style, you still need the for loop.

int** matrix = (int*)malloc(rows * cols * sizeof(int) + rows * sizeof(int*));

for (int i = 0; i < rows; i++) {
    matrix[i] = matrix + rows * sizeof(int*) + rows * cols * sizeof(int) * i;
}

Untested, but you get the idea. Otherwise, I'd stick with what Jason suggests.

Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • this only works if `sizeof (int) == sizeof (int *)` - otherwise, the offset will be wrong; it actually might be wrong even if this is the case – Christoph Jan 24 '10 at 20:59
  • @Christoph: Good point, and that's easy to work around too, but like I noted in my answer, this is untested. Fixed this now. – Matthew Scharley Jan 24 '10 at 21:20