# Thread: 2D Dynamically allocated pointer arrays

1. ## 2D Dynamically allocated pointer arrays

Hi!

I'm trying to create (insert subject)!

I get an error "missing ';' before type" on the line where I declare my pointer. Can anyone tell me what I'm doing wrong?

Code:
```
#include<stdio.h>
//#include<stdlib.h>

/*

This program demonstrates recursive functions and dynamic, multi-dimensional pointer arrays.

It will calculate the total factorial value for multiple groups of items.

You enter the total number of items, and the number of groups you will have.  Then you enter the
number of items in each group.  The program error-checks to make sure the number of items
entered in each groups adds up to be the total number of items.

*/

//	Prototypes.

unsigned long factr (unsigned long n);

void main ()
{

//	These are in order of appearance.

unsigned long num_items = 0;
unsigned long num_groups = 0;
unsigned long loop = 0;
unsigned long total = 0;
unsigned long quantity = 0;
unsigned long numerator = 0;
unsigned long denominator = 1;

printf ("\n\nHow many items total?\n");
scanf ("%u", &num_items);

printf ("\n\nHow many groups?\n");
scanf ("%u", &num_groups);

if (num_groups > num_items)
{
printf("\n\nError! Can't have more groups than items!\n\n");
exit (1);
}

//	Array dimensioning.

unsigned long *group_total[num_groups][2];
group_total = malloc (num_groups*2*sizeof(int));

if(!group_total)
{
puts ("\n\nERROR! Not enough Memory!\n\n");
exit (1);
}

//	Array initialization.

for (loop = 1; loop <= num_items; loop++)
{
group_total[loop][1] = 0;
group_total[loop][2] = 0;
}
loop = 0;

//	Array data-entry.

for (loop = 1; loop <= num_groups; loop++)
{
printf ("\n\nHow many in group %d\n", loop);
scanf ("%u", &quantity);

group_total[loop][1] = quantity;
total = total + quantity;
}
loop = 0;

//	Error checking and factorial calculations for each group

if (total = num_groups);
{
for (loop = 1; loop <= num_groups; loop++)
{
group_total[loop][2] = factr (quantity);
}
loop = 0;
}
else
{
printf ("\n\nTotal number of items not equal to total items entered!\n\n");
free (group_total);
exit (1);
}
total = 0;

//	Final calculations.

numerator = factr (num_items);

for (loop = 1; loop <= num_groups; loop++)
{
denominator = denominator * group_total[loop][2];
}
total = numerator / denominator;
printf ("\n\nTotal factorial for this mess: %u\n\n", total);
total = 0;
loop = 0;
free (group_total);
}

//	Factorial engine.

unsigned long factr (unsigned long n)
{
unsigned long answer;

if (n==1) return (1);
answer = n==0 ? 1: n * factr (n - 1); // recursive call
return (answer);
}```

2. In C90, declare variables before any statements.

3. I thought that was the problem... :-(

Can I make my pointer declaration a function by itself and retain the pointer after the function returns?

mw

4. >Can I make my pointer declaration a function by itself and retain the pointer after the function returns?

I don't think I fully understand, but sure.

There are plenty of issues with your code that are handled in the FAQ.
Code:
`for (loop = 1; loop <= num_items; loop++)`
Arrays are indexed from 0 to N-1, not 1 to N.

5. What I meant was:

The program asks the user how many groups there are and then declares a pointer array of that size. I can do this by calling a function that declares a pointer, but then when the function returns the pointer is gone.

Since I'm already using a recursive function, I want to close all of the extra functions before I start "recursing". I guess I can call a function that sets up my pointer and then calls the recursive function to perform my calculations, but is this going to "flood my stack" or whatever?

I know about the starting index of an array being zero but aren't pointers indexed starting at one?

mw

6. Originally Posted by Lionmane
What I meant was:

The program asks the user how many groups there are and then declares a pointer array of that size. I can do this by calling a function that declares a pointer, but then when the function returns the pointer is gone.
Perhaps pass a pointer to pointer. Also,
http://www.eskimo.com/~scs/C-faq/q6.16.html

Originally Posted by Lionmane
I know about the starting index of an array being zero but aren't pointers indexed starting at one?
No. Pointers point.

7. Ok, I've changed my code:

Code:
```
#include<stdio.h>
#include<stdlib.h>

/*

This program demonstrates recursive functions and dynamic, multi-dimensional pointer arrays.

It will calculate the total factorial value for multiple groups of items.

You enter the total number of items, and the number of groups you will have.  Then you enter the
number of items in each group.  The program error-checks to make sure the number of items
entered in each groups adds up to be the total number of items.

*/

//	Prototypes.

unsigned long factr (unsigned long num_items2, unsigned long num_groups2);
unsigned long factorial_engine (unsigned long n);

void main ()
{
unsigned long num_items = 0;
unsigned long num_groups = 0;

printf ("\n\nHow many items total?\n");
scanf ("%u", &num_items);

printf ("\n\nHow many groups?\n");
scanf ("%u", &num_groups);

if (num_groups > num_items)
{
printf("\n\nError! Can't have more groups than items!\n\n");
exit (1);
}
else
{
factr (num_items, num_groups);
}
}

unsigned long factr (unsigned long num_items2, unsigned long num_groups2)
{

//	These are in order of appearance.

unsigned long loop = 0;
unsigned long total = 0;
unsigned long quantity = 0;
unsigned long numerator = 0;
unsigned long denominator = 1;

//	Array dimensioning.

unsigned long *group_total;
group_total = malloc (num_groups2*2*sizeof(int));

if(!group_total)
{
puts ("\n\nERROR! Not enough Memory!\n\n");
exit (1);
}

//	Array initialization.

for (loop = 1; loop <= num_items2; loop++)
{
group_total[loop][1] = 0;
group_total[loop][2] = 0;
}
loop = 0;

//	Array data-entry.

for (loop = 1; loop <= num_groups2; loop++)
{
printf ("\n\nHow many in group %d\n", loop);
scanf ("%u", &quantity);

group_total[loop][1] = quantity;
total = total + quantity;
}
loop = 0;

//	Error checking and factorial calculations for each group

if (total = num_groups2);
{
for (loop = 1; loop <= num_groups2; loop++)
{
group_total[loop][2] = factr (quantity);
}
loop = 0;
}
else
{
printf ("\n\nTotal number of items not equal to total items entered!\n\n");
free (group_total);
exit (1);
}
total = 0;

//	Final calculations.

numerator = factr (num_items2);

for (loop = 1; loop <= num_groups2; loop++)
{
denominator = denominator * group_total[loop][2];
}
total = numerator / denominator;
printf ("\n\nTotal factorial for this mess: %u\n\n", total);
total = 0;
loop = 0;
free (group_total);
}

//	Factorial engine.

unsigned long factorial_engine (unsigned long n)
{
unsigned long answer;

if (n==1) return (1);
answer = n==0 ? 1: n * factr (n - 1); // recursive call
return (answer);
}```
But now when I tried to reference a subscript in group_total it gives me "subscript requires array or pointer type". I think it's telling me I didn't declare my pointer as a 2D array.

I looked up that link you gave me about multi-dimensional arrays, but I don't understand it.

mw

8. Looking at your code:

Arrays are indexed from 0 to N-1, not 1 to N.
You forgot to change your code for this.

>void main ()
main return an int:
Code:
`int main(void)`
> if (total = num_groups2);
This statement contains two errors:
1) = means assignment not equality.
2) The semicolon at the end means everything following the if() gets executed regardless of the outcome of the condition.

> group_total[loop][1] = 0;
> group_total[loop][2] = 0;
If you're not using the second element, then just make this one dimension.
Code:
`		group_total[loop] = 0;`

9. > unsigned long *group_total;
> group_total = malloc (num_groups2*2*sizeof(int));
If you're trying to malloc the equivalent of unsigned long group_total[num_groups2][2];
This is what you do

Code:
```  unsigned long (*group_total)[2];
group_total = malloc ( num_groups2 * sizeof *group_total );```
Be very careful here, (*group_total)[2] is NOT the same thing as *group_total[2], so don't go leaving out the () for the fun of it, it simply won't work.

By the way, this only works if your minor dimensions are constant. If they vary, then you need to start with unsigned long **group_total

Then you need to fix all your loops to index from 0 to N-1
Code:
```for ( i = 0 ; i < num_groups2 ; i++ ) {
for ( j = 0 ; j < 2 ; j++ ) {
group_total[i][j] = 0;
}
}```
When you're done, it's simply
Code:
`  free( group_total );`

10. Thanks guys! I'm still not understanding pointers very well it seems... :-(

The "C for Dummies" has little to no info about pointers. I have "The Complete Reference: C" by Herbert Schildt but I couldn't figure it out with that either.

Anyway, I was finally able to compile without any errors but now I'm getting a pop-up window that says "Debug Error!" and gives me some obscure message. The program runs fine until it begins calculating the factorials.

The error is "Damage: after Normal block (#44) at 0x00431DF0." Any ideas there? Sorry to ask so many questions. I'm trying to learn C pretty much on my own.

mw

11. If the size of the array varies, you have to dynamically allocate the rows and columns:

Code:
```//allocate 1D array of pointers, one pointer per row

a = (int **) calloc(row, sizeof(int *));

//allocate one column element array of ints for each row

for (i=0; i<row; ++i)
{
a[i]=(int *) calloc(column, sizeof(int));

//fill the matrix
for (i=0; i< row; ++i)
{
for (j=0; j<column; ++j)
a[i][j] = 2;
}
}```
calloc fills the array with 0's automatically. You can have the user specify what the number of rows and columns is.

See if that helps.

12. Don't cast malloc and calloc in C. (Or any other function that returns a void * for that matter.)

Quzah.

13. Quzah, how do you create 2D dynamic arrays (first subscript is dynamic, second is static)? I thought malloc was used to check the memory.

mw

14. I never said to not use malloc. I said don't typecast it's return.
Code:
```char **twodee;
int numofrows = 5, numofcols = 10, x;

twodee = malloc( sizeof( char * ) * numofrows );
for( x = 0; x < numofrows; x++ )
twodee[ x ] = malloc( sizeof( char ) * numofcols );```
The 'sizeof( char )' is just to illustrate the point, were this any other type than characters. The reason being, 'sizeof( char )' always evaluates to one, so it's not needed in this example. Were this any other type, it would be needed there (of the appropriate type (int, float, struct foo, etc etc).

Quzah.

15. > The error is "Damage: after Normal block (#44) at 0x00431DF0." Any ideas there?
Yeah, you modified some memory which wasn't yours.
Typically, you walked off the end of whatever array you allocated.

Post some more code.

> The Complete Reference: C" by Herbert Schildt
Oh dear - hope you still have the receipt, and time to take it back.
http://www.plethora.net/~seebs/c/c_tcr.html
A book so famed in infamy, it's got it's own buzzword
http://catb.org/~esr/jargon/html/B/bullschildt.html

Popular pages Recent additions