# Making a 2d array (matrix) in a struct

This is a discussion on Making a 2d array (matrix) in a struct within the C Programming forums, part of the General Programming Boards category; If I'm trying to make a 2d array in a struct, do I have to make the struct a certain ...

1. ## Making a 2d array (matrix) in a struct

If I'm trying to make a 2d array in a struct, do I have to make the struct a certain size when I write the prototype? I can't explain it very well, but here's what I'm talking about:

Code:
```{
int Matrix[][];
int row;
int column;
};```
This is what I have ^

I want it to think I have 1 matrix that looks like:

Code:
```{
int Matrix[30][25];
int row = 30;
int column = 25;
}```
and I want another matrix that looks like:

Code:
```{
int Matrix[25][10];
int row = 25;
int column = 10;
}```

So I can multiply the matrices to get one that looks like

Code:
```{
int Matrix[30][10];
int row = 30;
int column = 10;
}```
Can I make the Matrices a certain size "on the go", or do I have to make them all 50x50, just in case I have on the size of 50x50?

I fail at explaining, I hope you understood my question...Sorry if I gave you a headache :|

2. Code:
```struct matrix
{
int** values;
};

matrix mtrx;

// allocate it as so...
mtrx.values = new int*[width]; // allocates one dimension

for(int i = 0; i < size; i++) {
mtrx.values[i] = new int[height]; // allocates the second dimension
}```

3. Methinks your first example will be a compiler error.

Can I make the Matrices a certain size "on the go", or do I have to make them all 50x50, just in case I have on the size of 50x50?
You can't resize something declared this way:
Code:
`int mat[20][30];`
However, you could use a pointer to a pointer:
Code:
`int **mat;`
And later make it any size you want -- which you must, since as is it has no dimensions at all.
Code:
```int i, rows, cols, **mat;
mat = malloc(rows*sizeof(int*));
for(i=0;i<rows;i++) mat[i] = malloc(cols*sizeof(int));```
Notice the first malloc is an array of pointers (int*) whereas the second one is for the actual array of (int). After that you can use mat[x][x] normally.

4. Originally Posted by scwizzo
Code:
```mtrx.values = new int*[width]; // allocates one dimension

for(int i = 0; i < size; i++) {
mtrx.values[i] = new int[height]; // allocates the second dimension
}```
What is "new" supposed to do?

Btw, thanks for the help. I guess I had tunnel vision about the ways it could be done

What is "new" supposed to do?

6. Originally Posted by MK27
oops, i forget what part of the forum I'm in sometimes. Use malloc() instead of new. MK27 has the C way to do it, th way I listed is C++. Essentially 'new' is the C++ way to use malloc.

I'm trying to understand this code, but some of it doesn't make sense to me.

Code:

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

How do you know that you're supposed to do sizeof(int*)?
If I understand it correctly, you're just multiplying rows x the "sizeof" a column?
**mat is a pointer (to a pointer), with no memory allocated.

You need to set "rows" to a definate value, obviously, eg, 50. Then:
mat = malloc(rows*sizeof(int*))
This allocates enough space for 50 int pointers. The reason we need int pointers is because each first dimension element of mat will also be a pointer (to an actual array of ints) -- that's why mat is a "pointer to a pointer". This parallels the fact that it makes no sense to refer to a matrix value, mat[11] -- however, you can refer to the 11th row. And (to reiterate), in the code, mat[11] is literally a pointer to a 1 dimensional array of ints (ie, a row in your matrix).

Next, each of those 50 row pointers needs space for an actual row. The length of the row is determined by the number of columns (say 30).
for (i=0;i<rows;i++) mat[i] = malloc(cols*sizeof(int));
That's why we use (int) here but (int*) previously.

Seems a bit complicated just for a 2D matrix, doesn't it (this is why C is considered "low level" -- it must attend to a lot of fine details). Why can't you just go:

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

You can. That's all the same you need for 1000 (rows*cols, if rows is 50 and cols 20) ints. The problem is, that will be a one dimensional array of 1000, like:

int array[1000]

which you could use both to store a matrix, but you will keep having to do some weird math in order to find your elements. That's awkward for the programmer and most likely less optimal for the compiler as well.

8. Thanks for the lengthy explanation, it helps a lot.

Say I make a declaration:

int ***mat;

What is the type of
**mat
*mat
mat

Are they all int's?

I deleted my last post because I was going to ask it in a different way, but you explained it well enough.

9. All but the last one are pointers to ints (mat by itself is an int). Hence they will all be 4 bytes in size on a 32 bit machine, it's true even for a declaration like: char *mat; by the way.

Say I make a declaration:
int ***mat;
Say you don't Seriously -- what would be the purpose of this?

Not to say it never happens, but they are not considered good style, and WRT matrices, no matter how many dimensions to your matrix (mat[10][10][10][10]), none of them will contain a *** -- you will just get layers of **. I'll leave you to think about why.

What is the type of
**mat
*mat
mat

Are they all int's?
int **mat is a pointer to an int pointer.
int *mat is an int pointer.
int mat is just an int.

None of them has to involve an array, eg:
Code:
`int mat, *p = &mat, *p2 = &p;`
"Pointers to pointers" are also used to pass the address of a pointer to a function so that it can be reassigned:
Code:
```void example_func(int **ptr);  /* prototype */
int x, *ptr=&x;
example(&ptr);  /* a call */```
Inside example_func, you can now ressign ptr to something other than x and the consequences will be global (x will remain unchanged). You'll run into a need for that sooner or later.

11. Originally Posted by MK27
int **mat is a pointer to an int pointer.
int *mat is an int pointer.
int mat is just an int.
Yeah, that is a more correct way of putting it.

12. Originally Posted by MK27
Say you don't Seriously -- what would be the purpose of this?
Just to get a better understanding of how these bastard pointers work

One thing I hate about C, are the pointers. In fact, it may be the only thing I hate about C. I understood them last semester, and then I took a memory dump over the winter break.

As far as I'm concerned, pointers are the least of my worries. If I understood them last semester, I'll be able to re-learn them in no time.

13. A pointer is just like any other variable. It holds a value. Everything in C holds a value. Everything. Some values are characters, some are numbers, some are addresses. If it's a pointer, it's holding an 'address of variable type N' as its value.

Quzah.

Just to get a better understanding of how these bastard pointers work

One thing I hate about C, are the pointers. In fact, it may be the only thing I hate about C. I understood them last semester, and then I took a memory dump over the winter break.

As far as I'm concerned, pointers are the least of my worries. If I understood them last semester, I'll be able to re-learn them in no time.
Hmm. I started a page to explain pointer usage (kind of) a while ago, to save having to explain some things, and still haven't got around to finishing it, but you may want to have a look anyway:

Pointers: Pass by Value, Pass by Reference

I kind of focus on the fact that a pointer has three values associated with it:
Code:
```int x, *ptr=x;   /* declaration */
ptr;     /* the value stored in ptr -- the address of x */
&ptr;    /* the address of ptr itself */
*ptr;     /* the value stored in the variable at the address stored in ptr */```
whereas a normal variable (such as x) only has two.

15. You guys have helped a lot, thanks for everything. I just have to add 1 more function (multiplying matrices) and I'm finished. I'll take a look at that page when I'm finished.