0

I came across an old code where I need to allocate memory for an array of matrices. Currently it is done by creating a structure matrix and allocating memory by making an arrray of structures.

Like so.

struct matrix
{
    int x[13][13];
};
int main()
{
    matrix *push = (matrix*)malloc(sizeof(matrix) * 1000);
    //do stuff
    free(push);
    return 0;
}

But now the question.. Do I really need to do this? I know I am allowed to declare a variable of type int *matrix[13][13];

But I cant seem to figure out a way to allocate memory to this variable.

I tried matrix = (int***)malloc(sizeof(int[13][13])*1000); which results in E0137 expression must be a modifiable lvalue and honestly in doesnt seem correct either

I know there are many better and creative ways of allocating an array like this, but I am curious

Questions

  1. int *matrix[13][13] what will this kind of variable even mean or represent? Is it a pointer to a 2D matrix or s it an pointer to an array of 2D matrices?
  2. How will I use the above mentioned variable?
  3. How will I allocate memory for the above variable without using any more variables?

Clarifications From comments it seems int *matrix[13][13] represents a matrix of 13x13 int*

What I am asking is actually, is there a way to have a variable with a dynamically allocated first dimension and static 2nd and 3rd dimensions without using structures typedefs etc

EDIT As pointed out by felix what I am looking for is int (*matrix)[13][13] = (int(*)[13][13])malloc(1000*sizeof(matrix));

Siddharth Chabra
  • 448
  • 6
  • 22
  • Don't go OTT with three stars. `int *matrix[13][13]` is a 2D array of pointers to `int`. Is that what you need, or some `int` arrays each size 13x13? – Weather Vane Jul 26 '18 at 19:43
  • This question probably provides the best solution if you want a true 3d array: https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays – Andrew Henle Jul 26 '18 at 19:44
  • 3
    I guess you're looking for `int (*matrix)[13][13] = malloc(1000 * sizeof *matrix);` –  Jul 26 '18 at 19:44
  • or, instead of the `struct`, you could also just use a `typedef`, which would avoid the "messy" declaration of a pointer-to-array. Without the parantheses, it's an array-of-pointers instead. –  Jul 26 '18 at 19:46
  • @AndrewHenle I dont want to allocate a multi dimensional array. I know how to do that i am curios to know what this variable represents – Siddharth Chabra Jul 26 '18 at 19:47
  • @SiddharthChabra Stated. It's an array of array of pointers. (an array of 13 arrays of 13 pointers each). And given what you seem to want, it's useless. – WhozCraig Jul 26 '18 at 19:48
  • @FelixPalmen already using a struct, and typdef is similar – Siddharth Chabra Jul 26 '18 at 19:48
  • @SiddharthChabra yes, you want to allocate a multi-dimensional array. The code with the `struct` around does basically just this. –  Jul 26 '18 at 19:48
  • @rcgldr no, as `matrix` is not a **type** in my line. The type of `matrix` is the pointer, so `sizeof(matrix)` would be just the size of a pointer. –  Jul 26 '18 at 19:49
  • `int *matrix[13][13]` is an [array 13 of array 13 of pointer to int](https://cdecl.org/?q=int+*matrix%5B13%5D%5B13%5D) - great web-site. – chux - Reinstate Monica Jul 26 '18 at 19:49
  • I wanted to know if the was a way to have a variable with a Dynamic 1st dimention and static 2nd 3rd dimentions in C – Siddharth Chabra Jul 26 '18 at 19:49
  • @rcgldr `sizeof(matrix)` is the size of a variable of pointer type. Felix has it right. Optionally, `calloc` also works: `int (*matrix)[13][13] = calloc(1000, sizeof *matrix);` – WhozCraig Jul 26 '18 at 19:50
  • 1
    @SiddharthChabra which is a multi-dimensional array that you dynamically allocate. Have a look at Andrew's link instead of complaining. I commented the correct line for allocation above. –  Jul 26 '18 at 19:50
  • @FelixPalmen - deleted my prior comment, I only meant to change `matrix` to `push`. – rcgldr Jul 26 '18 at 19:51
  • Try `struct matrix *array_of_matrices = malloc(sizeof *array_of_matrices * N);` – chux - Reinstate Monica Jul 26 '18 at 19:51
  • @SiddharthChabra "*already using a struct, and typdef is similar*" <- no, it isn't. Not at all. And you should work a little on your attitude. –  Jul 26 '18 at 19:52
  • @SiddharthChabra The answer to your clarified question is *exactly* what Felix showed you. There are no typedefs nor structs in that allocation. The superior dimension is dynamic, the rest are static, *exactly* as you requested. – WhozCraig Jul 26 '18 at 19:53
  • `How will I use the above mentioned variable?` push[i] or *(push + i) would point to the "ith" 13 by 13 matrix. – rcgldr Jul 26 '18 at 19:54
  • @WhozCraig malloc requires a type cast (atleast in VS) what type cast do I use? – Siddharth Chabra Jul 26 '18 at 19:56
  • 1
    @SiddharthChabra in standard C it does *not* require a typecast. MS's braindead implementation of the standard will warn, but not fail to compile that line. Bonified C compilers will happily accept it. In standard C you need *not* cast to, or from, `void *` to non-const object pointer types. If you are using MS's compiler, you can either (a) disable that *specific* warning in those specific locations via pragma, (b) use a typedef alias and cast against that, (c) long-hand it and use `(int(*)[13][13])` as the cast. That MS continues to warn against that has been a frustration for years. – WhozCraig Jul 26 '18 at 20:00
  • 1
    Your edit is wrong. The "harmless" part is the unnecessary and very ugly cast. The real problem is, your type is still wrong. Also, don't edit an answer into a question. That's what the answers are for. If something is missing (shouldn't be the case here), you can self-answer. –  Jul 26 '18 at 20:06
  • `int (*matrix)[13][13] = (int(*)[13][13])malloc(1000*sizeof(matrix));` is almost right. Use `int (*matrix)[13][13] = malloc(sizeof *matrix * 1000);`. Drop the cast and use `*matrix` in the size calculation. – chux - Reinstate Monica Jul 26 '18 at 20:34

2 Answers2

2

No, you don't want to use

int *matrix[13][13];

That will declare a [13][13] array of int*s.

You need

// pointer to "an array of 13 x 13 ints"
int (*matrix)[13][13];

or simplify it by using a type alias.

typedef int matrix_type[13][13];
matrix_type* matrix_ptr;

You can allocate memory for such a variable using

matrix_type* matrix_ptr = malloc(1000*sizeof(*matrix_ptr));

and assign values to it using

matrix_ptr[0][0][0] = 0;

...

matrix_ptr[999][12][12] = 0;
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • `using` in C? interesting – 0___________ Jul 26 '18 at 19:55
  • @P__J__, sorry. Got mixed up with the tags. – R Sahu Jul 26 '18 at 19:56
  • and now you repeat my answer :) – 0___________ Jul 26 '18 at 19:56
  • 1
    @P__J__ Only partially - this answer shows how to correctly have a pointer to array *without* typedef... – Aconcagua Jul 26 '18 at 20:07
  • 2
    @P__J__ always write complete and self-contained answers. Comments are considered irrelevant when it comes to answering. –  Jul 26 '18 at 20:09
  • @FelixPalmen - in my answer I just want to show thy this not very good typedef way may by convenient at some stage of the C learning. – 0___________ Jul 26 '18 at 20:11
  • @P__J__ which makes it a *partial answer*, which is fine as well. But a *complete* answer is always better -- I just wanted to point out that comments don't matter. If they contain part of the answer, repeat it anyways (and, possibly, elaborate on it). I could have written an answer myself, but I was too lazy ;) –  Jul 26 '18 at 20:26
  • @FelixPalmen - repeating the comments is IMO not OK, as person who has commented may write the answer later in more convenient time – 0___________ Jul 26 '18 at 20:51
2

I have noticed that sometimes beginner programmers are finding typedef-ing the multidimensional matrices which have to be dynamically allocated easier as it reduces the problem to the single star pointer and the sizeof of the defined type and pointer to it is much easier to understand.

#include <stdio.h>

typedef int my13x13matrix[13][13];

int main(void) {
    my13x13matrix *mylargematrix = malloc(1000 * sizeof(*mylargematrix));

    mylargematrix[999][12][12] = 5;

    printf("%d \n", mylargematrix[999][12][12]);
    return 0;
}

you can also use the single star pointer arithmetic.

my13x13matrix *anotherpointer = &mylargematrix[10];
(*anotherpointer)[5][5] = 1;
anotherpointer++;
(*anotherpointer)[5][5] = 2;

printf("%d %d\n", mylargematrix[10][5][5], mylargematrix[11][5][5]);
0___________
  • 60,014
  • 4
  • 34
  • 74