# Pointer to a 2d array

This is a discussion on Pointer to a 2d array within the C Programming forums, part of the General Programming Boards category; I'm trying to write a program that will create and work with matrices, but im having problems with a pointer ...

1. ## Pointer to a 2d array

I'm trying to write a program that will create and work with matrices, but im having problems with a pointer to a 2d array.

I created this structure in a header file:
Code:
```typedef struct {
int  rowdim, coldim;
double* element;
} matrix;```
the header file also has the function prototypes.

Here is the file where i define the functions:
Code:
```#include "matrix.h"

matrix create_empty(int rdim, int cdim)
{
matrix* new_matrix;
new_matrix = malloc(sizeof(matrix));
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
return *new_matrix;
}

matrix create_initval(int rdim, int cdim, double* values)
{
int i, j;
matrix* new_matrix;
new_matrix = malloc(sizeof(matrix));
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
for (i=0; i<cdim; i++)
{
for(j=0; j<rdim; j++)
new_matrix -> element[i][j] = values[i][j];
{
return *new_matrix;
}

void destroy(matrix a)
{
free(&a.element);
}

void matrix_print(matrix a)
{
int i, j;
printf("\n");
for (i=0; i<a.coldim; i++)
{
for(j=0; i<a.rowdim; j++)
{
printf(" %f ", a.element[i][j]);
}
}
}
}```
however, there is a compile error for:
Code:
`new_matrix -> element[i][j] = values[i][j];`
that reads: subscripted value is neither array nor pointer

Im not sure why, because i know the program works when creating a one dimensional vector, but when its 2d, i have the problem

2. i read something online about a double pointer being used when working with 2d arrays, but how exactly are they used?

3. You can still do this properly without changing your design. Accesses to your matrix will look like this.

newmatrix->element[j * rdim + i] = values[j * rdim + i];

This works because the memory is contiguous, so item 42 is actually item (7, 6) or what have you. That's why you calculate.

4. Alright, so i changed my code to:
Code:
```#include "matrix.h"

matrix create_empty(int rdim, int cdim)
{
matrix* new_matrix;
new_matrix = malloc(sizeof(matrix));
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
return *new_matrix;
}

matrix create_initval(int rdim, int cdim, double* values)
{
int i, j;
matrix* new_matrix;
new_matrix = malloc(sizeof(matrix));
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
for (i=0; i<cdim; i++)
{
for(j=0; j<rdim; j++)
new_matrix -> element[j * rdim + i] = values[j * rdim + i];
{
return *new_matrix;
}

void destroy(matrix a)
{
free(&a.element);
}

void matrix_print(matrix a)
{
int i, j;
printf("\n");
for (i=0; i<a.coldim; i++)
{
for(j=0; i<a.rowdim; j++)
{
printf(" %f ", a.element[j * rdim + i]);
}
}
}
}
}```
I also created a test file that looks like:

Code:
```#include "matrix.h"

int main()
{
double one[2][3] = {
{1,2,3},
{4,5,6}
};

matrix m_one;
m_one = create_initval(2, 3, *one);
matrix_print(m_one);
return 0;
}```
but when i compile, i get:
/tmp/ccgEP8z2.o: In function `main':
test.c.text+0x7d): undefined reference to `matrix_print'
collect2: ld returned 1 exit status

5. I see you used the suggestion above to use a one-dimensional array. I'd suggest not to sacrifice readability and other assumptions one might have about a (your) matrix. Matrices are inherently two-dimensional, thus you should make it two dimensional. Again, my opinion.

As for your compile error, its probably because you need to pass both .c filenames when you compile (the matrix and test .c files).

6. well how would i keep it as a two dimensional array? Im thinking that I'll have to use a double pointer, but dont know how to set that up.

7. First, are your compiler errors gone?

Next, 2-d arrays are just "arrays of arrays". 3-d arrays are "arrays of arrays of arrays", etc.. So for a 2-d array you'd declare it as (for, say, ints)
Code:
`int ** myArrays;`
Then this variable doesnt really point to anything useful, so you need to assign some memory to the first of it's two dimensions, say like
Code:
`myArrays = malloc(sizeof(int*) * ROWS);`
Where "ROWS" is of course set, and you do the appropriate error checking. Recall that, since it is basically an "array of arrays", we are using the size of "int*" rather than "int". Next, for each of these rows, you allocate some memory for the corresponding column
Code:
`myArrays[curRow] = malloc(sizeof(int) * COLS);`
Then you can read/write to the matrix, via "myArrays[rowNum][colNum]".

Make sure that you "free" all memory you "malloc"ed. So you must iterate over the rows and free each column (freeing the second dimension). Then you can simply "free" "myArray" (the first dimension).

8. so i changed my structure to:
Code:
```typedef struct {
int  rowdim, coldim;
double** element;
} matrix;```
and then my other code to:
Code:
```#include "matrix.h"

matrix create_empty(int rdim, int cdim)
{
matrix* new_matrix;
new_matrix = malloc(sizeof(matrix));
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix -> element = malloc((rdim*cdim) * sizeof(double));
return *new_matrix;
}

matrix create_initval(int rdim, int cdim, double* values)
{
int i, j, k;
matrix* new_matrix;
new_matrix = malloc(sizeof(double*) * rdim);
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
for (k=0; k<rdim; k++)
new_matrix -> element[k] = malloc(sizeof(double) * cdim);
for (i=0; i<cdim; i++)
{
for(j=0; j<rdim; j++)
new_matrix -> element[i][j] = values[i][j]; // does not work
{
return *new_matrix;
}

void destroy(matrix a)
{
free(&a.element);
}
}```
but im still not sure how to pass a 2d array into the function and write it to matrix

9. Are you going to answer my question above?

Modifying the contents of the struct shouldn't change how the struct is passed around--you should be able to pass it/receive it the same way as with "elements" being 1D.

I described above, you "malloc" the number of rows--once. It seems your doing this "rdim" number of times. Then you use a loop and "malloc" a column for each row, so thats when you'd use the for loop.
Code:
```	for (k=0; k<rdim; k++)
new_matrix -> element[k] = malloc(sizeof(double) * cdim);```
You're using the "k"th element, without having allocated the memory for it first. Before this line, is when you'd probably allocate the memory for the rows, then this for loop should work fine for allocating each column.

Also, you aren't "free"ing properly. Read what I said above, I'm not going to repeat it.

10. but im still not sure how to pass a 2d array into the function and write it to matrix
If its an "actual" array, like you've declared it as
Code:
`double values[3][5];`
or whatever dimensions, then you (obviously) already know the dimensions of the values array, so it would be passed like
Code:
`void myFunction(double values[3][5])`
If you dont know the dimensions (which is probably the case), then values was probably declared like elements, like
Code:
`double** values;`
. In this case, the function would be declared as
Code:
`void myFunction(double** values)`
In either case, it should be called the same, like
Code:
`myFunction(values);`

11. First off, thanks for being patient...im new to programming.

Second the only compile errors refer to
Code:
```for(j=0; j<rdim; j++)
new_matrix -> element[i][j] = values[i][j]; // does not work```
it says: error: subscripted value is neither array nor pointer

I also changed the code to:
Code:
```for (k=0; k<cdim; k++)
new_matrix -> element[k] = malloc(sizeof(double) * cdim);```

the code that im compiling with the function declerations is:
Code:
```#include "matrix.h"

int main()
{
double one[2][3] = {
{1,2,3},
{4,5,6}
};

matrix m_one;
m_one = create_initval(2, 3, *one);
matrix_print(m_one);
return 0;
}```

12. Second the only compile errors refer to
I was referring to your initial compilation error, regarding the undefined reference. I imagine thats fixed now though.

Next, I think I explained it well enough in my previous post (Pointer to a 2d array), as best as I could without giving you the exact solution, in which case you wont learn (i.e. a bad thing). Try and re-read it again to understand what it is saying. What I described in that post can be found online, for example, this a basic search yields this link: 23.2: Dynamically Allocating Multidimensional Arrays. The first example there is of interest.

Try to read and understand this, then if you have a problem implementing it or you're getting an error, post all of your code and the exact and complete error/warning message(s).

13. I understand how to set up the matrix, but im now having trouble passing in an 2d array.

The array is set up as:
Code:
```double one[2][3] = {
{1,2,3},
{4,5,6}
};

matrix m_one;
m_one = create_initval(2, 3, *one);```
"one is then passed into the function:
Code:
```matrix create_initval(int rdim, int cdim, double* values)
{
int i, j, k;
matrix* new_matrix;
new_matrix -> rowdim = rdim;
new_matrix -> coldim = cdim;
new_matrix = malloc(sizeof(double*) * rdim);
for (k=0; k<rdim; k++)
new_matrix -> element[k] = malloc(sizeof(double) * cdim);
for (i=0; i<cdim; i++)
{
for(j=0; j<rdim; j++)
new_matrix -> element[i][j] = values[i][j]; // does not work
{
return *new_matrix;
}```
the program works fine, when is et "element[i][j] = number", but if it is like I have it above, i get the compile error:
subscripted value is neither array nor pointer

which i know is refering to the "values[i][j]"

14. If you declare the array of values as
Code:
`double one[2][3]`
then the argument to the function can be the same, like
Code:
`matrix create_initval(int rdim, int cdim, double values[2][3])`
When you call it, you dont dereference it (like you are above, by using "*"), simply pass it like
Code:
`create_initval(2, 3, one);`
Next, inside the function in question
Code:
```matrix* new_matrix;
new_matrix -> rowdim = rdim;
// etc```
You declare a pointer and start using it without allocating it any memory. This is certainly undefined behaviour and not good. In fact, I dont think there is any point in making it a pointer, just declare it as
Code:
`matrix new_matrix;`
Then you'll have to replace the "->"s with "."s.

For this line
Code:
`	new_matrix = malloc(sizeof(double*) * rdim);`
You're overwriting the stuff you just set up (setting row dim, etc). You probably want it to be
Code:
`	new_matrix->element = malloc(sizeof(double*) * rdim);`
Of course after removing the pointer ("*"), the arrows will be dots, as described above.

Finally, after removing the pointer, the return statement will require the "*" to be removed as its not a pointer anymore.

15. i made all those corrections, but i still get the same compile error:
subscripted value is neither array nor pointer - referring to:
Code:
`new_matrix.element[i][j] = values[i][j];`
as well as a new error:
passing argument 3 of ‘create_initval’ from incompatible pointer type
referring to "m_one = create_initval(2, 3, one);" in:
Code:
```#include "matrix.h"

int main()
{
double one[2][3] = {
{1,2,3},
{4,5,6}
};

matrix m_one;
m_one = create_initval(2, 3, one);
matrix_print(m_one);
return 0;
}```

Page 1 of 2 12 Last