views:

100

answers:

5

Hey *, I'm currently trying to understand how to implement a 2-dimensional array of struct in C. My code is crashing all the time and I'm really about to let it end like all my approaches getting firm to C: garbage. This is what I got:

typedef struct {
    int i;
} test;

test* t[20][20];
*t = (test*) malloc(sizeof(test) * 20 * 20);

My glorious error:

error: incompatible types when assigning to type ‘struct test *[20]’ from type ‘struct test *’

Do I have to allocate the memory seperately for every 2nd dimension? I'm getting nuts. It should be so simple. One day I will build a time-machine and magnetize some c-compiler-floppies...

+3  A: 
test **t;

t = (test **)malloc(sizeof(test *) * 20);
for (i = 0; i < 20; i++) {
   t[i] = (test *)malloc(sizeof(test) * 20);
}
BobTurbo
You're missing a 20.
IVlad
Fixed. I hate c.
BobTurbo
+10  A: 

This should be enough:

typedef struct {
    int i;
} test;

test t[20][20];

That will declare a 2-dimensional array of test of size 20 x 20. There's no need to use malloc.

If you want to dynamically allocate your array you can do this:

// in a function of course
test **t = (test **)malloc(20 * sizeof(test *));
for (i = 0; i < 20; ++i)
    t[i] = (test *)malloc(20 * sizeof(test));
IVlad
+3  A: 

Other answers show how to fix it but they don't explain why. As the compiler hinted, the type of t in your original example is actually test *[20] which is why your cast to test * wasn't enough.

In C, the name of an array T of dimension N is actually of type *T[dim0][dim1]...[dimN-1]. Fun.

msw
A: 

From my observation, you may not know exactly what you want and confuse on the struct and pointer arithmetic. Please go through the following 2 possibilities.

1) A two dimensional array with each element has a pointer to test. In this case the memory of all the pointers to tests are already statically allocated. But, the memory of the real tests are not ready. In this case you must fill in the test [i][j] one by one.

Each of the test is discrete in the memory and you have the advantage of create or destroy them individually dynamically.

typedef struct {
    int i;
} test;

test* t[20][20]; 
/* or instead of statically allocated the memory of all the pointers to tests
   you can do the following to dynamically allocate the memory
   test ***t;
   t = (test***)malloc(sizeof(test *) * 20 * 20);
*/ 

for (int i=0; i < 20; i++){
   for (int j=0; j < 20; j++){
      t[i][j] = malloc(sizeof(test));
   }
}

2) A two dimensional array with each element is a test. In this case the memory of all the tests are already allocated. Also, the memory of the real tests are ready to use without extra preparation.

All of the tests are continuous in the memory as a big block and is always there. This mean that you may waste a chunk of memory if you only need all tests at certain peak time and most of the time you only use a few of them.

typedef struct {
    int i;
} test;

test t[20][20]; 
/* or instead of statically allocated the memory of all tests
   you can do the following to dynamically allocate the memory
   test **t;
   t = (test**)malloc(sizeof(test) * 20 * 20);
*/ 
ttchong
A: 

Also, as long as your inner dimension size is constant, you can allocate a variable number of counts of that inner dimension

int n = ...;
test (*t)[20] = malloc(sizeof (*t) * n);
t[0 .. (n-1)][0 .. 19] = ...;
Johannes Schaub - litb