Need Help (C Programming)

TecHNooB

Diamond Member
Sep 10, 2005
7,458
1
76
How would I make a two dimensional array using malloc? The size of the array is unknown until the program is run.
 

lousydood

Member
Aug 1, 2005
158
0
0
int **array; // example
int i, n=5,m=6; // dimensions

array = (int **) malloc (sizeof(int *) * n);
if (array == NULL) {
perror("malloc");
exit(1);
}
for(i=0; i<n; i++) {
array = (int *) malloc (sizeof(int) * m);
if (array == NULL) {
perror("malloc");
exit(1);
}
}

.
.
.

for(i=0; i<n; i++) free (array);
free (array);
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
For an x,y grid of data types it's basically y * (x * element size). Just calculate the size of the whole block and malloc it in one chunk, then set up your pointers correctly.

Edit lousydood beat me to the post :). But I am not sure what the benefit of individually allocating the rows is if the data type is homogenous and the arrays are not jagged.
 

TecHNooB

Diamond Member
Sep 10, 2005
7,458
1
76
Originally posted by: Markbnj
For an x,y grid of data types it's basically y * (x * element size). Just calculate the size of the whole block and malloc it in one chunk, then set up your pointers correctly.

Edit lousydood beat me to the post :). But I am not sure what the benefit of individually allocating the rows is if the data type is homogenous and the arrays are not jagged.

Oooh............. I see what you're saying. As much as I hate pointers, it makes a lot of sense. Thanks!
 

kamper

Diamond Member
Mar 18, 2003
5,513
0
0
Originally posted by: Markbnj
For an x,y grid of data types it's basically y * (x * element size). Just calculate the size of the whole block and malloc it in one chunk, then set up your pointers correctly.
Plus the space for the extra layer of pointers.
Edit lousydood beat me to the post :). But I am not sure what the benefit of individually allocating the rows is if the data type is homogenous and the arrays are not jagged.
Well, if your array is big, you might be able to find y blocks of size x*elementsize but not one single block of y*x*e. I have no idea how often that would come into play or how much memory you'd need to use though.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Originally posted by: kamper
Originally posted by: Markbnj
For an x,y grid of data types it's basically y * (x * element size). Just calculate the size of the whole block and malloc it in one chunk, then set up your pointers correctly.
Plus the space for the extra layer of pointers.
Edit lousydood beat me to the post :). But I am not sure what the benefit of individually allocating the rows is if the data type is homogenous and the arrays are not jagged.
Well, if your array is big, you might be able to find y blocks of size x*elementsize but not one single block of y*x*e. I have no idea how often that would come into play or how much memory you'd need to use though.

Yeah, for a really large chunk of data it might give you some memory management granularity; like a row-level paging scheme.

On the first point, the classic example of a 2D array in memory is a screen buffer. It's just y * (x * color_depth). The key point is that there is no fundamental difference in the memory layout of int[16], int[4][4], int[2][8], int[8][2], int[2][2][4], etc. It's all in how the indexes are interpreted.
 

MovingTarget

Diamond Member
Jun 22, 2003
9,002
115
106
What are you using a 2-dimensional array for? Is it just to store a regular matrix? If so, an easy way would be to use/include nrutil.h from numerical recipes. They have a function that uses malloc called matrix and freematrix that should make your life easier. Not sure if that would be what you are looking for though. Besides, the source you need to agree to a liscense to use.
 

kamper

Diamond Member
Mar 18, 2003
5,513
0
0
Originally posted by: Markbnj
Yeah, for a really large chunk of data it might give you some memory management granularity; like a row-level paging scheme.
Yep, that's what I was getting at.

On the first point, the classic example of a 2D array in memory is a screen buffer. It's just y * (x * color_depth). The key point is that there is no fundamental difference in the memory layout of int[16], int[4][4], int[2][8], int[8][2], int[2][2][4], etc. It's all in how the indexes are interpreted.
I'm probably missing something here, I haven't done any c development in a while (I actually started a thread on this topic a while ago, I should try to find it).

So, if you declare, say, an int[6][4], the compiler has to remember that your second dimension is 4. Otherwise it won't know how far to jump when you try to address something like foo[3][1]. What happens when you pass it to some function as an **int?

I thought that if you had a 2-d array, the first index would give you an array of pointers, from whence you would follow a pointer to your array of data, like in lousydood's example. Is there a difference between **int and int[][]?
 

aCynic2

Senior member
Apr 28, 2007
710
0
0
Originally posted by: lousydood
int **array; // example
int i, n=5,m=6; // dimensions

array = (int **) malloc (sizeof(int *) * n);
if (array == NULL) {
perror("malloc");
exit(1);
}
for(i=0; i<n; i++) {
array = (int *) malloc (sizeof(int) * m);
if (array == NULL) {
perror("malloc");
exit(1);
}
}

.
.
.

for(i=0; i<n; i++) free (array);
free (array);

First, I had to look this up, because I...oh...you did dereference the arrays, it's just Anandtech's forum software misinterpreting your [eye] as an italics tag. You only see it when you quote your text.

Nevermind.

There is one thing to consider and that is mult-dimensional arrays allocated like that are poor performers. You might want to consider allocationg a single large chunk and using a calculation to index into it instead.

Multi-dimensional arrays.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Originally posted by: kamper
Originally posted by: Markbnj
Yeah, for a really large chunk of data it might give you some memory management granularity; like a row-level paging scheme.
Yep, that's what I was getting at.

On the first point, the classic example of a 2D array in memory is a screen buffer. It's just y * (x * color_depth). The key point is that there is no fundamental difference in the memory layout of int[16], int[4][4], int[2][8], int[8][2], int[2][2][4], etc. It's all in how the indexes are interpreted.
I'm probably missing something here, I haven't done any c development in a while (I actually started a thread on this topic a while ago, I should try to find it).

So, if you declare, say, an int[6][4], the compiler has to remember that your second dimension is 4. Otherwise it won't know how far to jump when you try to address something like foo[3][1]. What happens when you pass it to some function as an **int?

I thought that if you had a 2-d array, the first index would give you an array of pointers, from whence you would follow a pointer to your array of data, like in lousydood's example. Is there a difference between **int and int[][]?

It's a little early in the AM for thinking about arrays and addresses, but I think you're confusing the actual layout of the data in memory with the _type_ of an expression involving the array. If you allocate an array int[4][4] the compiler will create a contiguous region of memory and perform the indexing calculations to address the right row and column.
 

kamper

Diamond Member
Mar 18, 2003
5,513
0
0
Originally posted by: Markbnj
It's a little early in the AM for thinking about arrays and addresses, but I think you're confusing the actual layout of the data in memory with the _type_ of an expression involving the array. If you allocate an array int[4][4] the compiler will create a contiguous region of memory and perform the indexing calculations to address the right row and column.
Gotcha (I also read my old text book about this). So a disadvantage then is that you have to set the row length at compile time for any functions which will process the array.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Originally posted by: kamper
Originally posted by: Markbnj
It's a little early in the AM for thinking about arrays and addresses, but I think you're confusing the actual layout of the data in memory with the _type_ of an expression involving the array. If you allocate an array int[4][4] the compiler will create a contiguous region of memory and perform the indexing calculations to address the right row and column.
Gotcha (I also read my old text book about this). So a disadvantage then is that you have to set the row length at compile time for any functions which will process the array.

It's been so long since I worked with unmanaged storage and did without collection classes. :). I think essentially you need to know the bounds for any interior dimensions at compile time, but the edge dimension can be freely calculated at runtime... or something like that. Of course you can always use pointer arithmetic and access the array any way you want to at run time.