# Dynamic 2 Dimensional Array

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 06-20-2008
mrb260478
Dynamic 2 Dimensional Array
Please go through the code below,
I want to create a dynamic 2 dimensional int array, to be created at run time.
Code:

```#include <stdio.h> #include <stdlib.h> void point(int **a,int row,int col) {   int i;     //printf ("\n%u\n",a);     a=(int **) malloc(sizeof(int *) * row);     if(a==NULL)   {       printf ("CAnnot allot space");       exit(1);   }     for(i=0;i<col;++i)   {       a[i]=(int *) malloc(sizeof(int) * col);       if(a[i]==NULL)       {         printf ("CAnnot allot space");         exit(1);       }   } } void main() {   int **p;   int i,j;   int row=7,col=7;     randomize();   //printf ("\n%u\n",p);   point(p,row,col);     for(i=0;i<row;++i)   {       for(j=0;j<col;++j)       {         p[i][j]=random(10);         //if(i==6 || i==9)             printf ("%d\n",p[i][j]);       }   }   printf ("Alloted\n");     for(i=0;i<row;++i)   {       for(j=0;j<col;++j)       {         //if(i==6 || i==9)             printf ("p[%d][%d] = %d\n",i,j,p[i][j]);       }   } }```
But it gives the following result :

2
3
6
4
0
5
8
3
7
5
2
3
1
4
8
2
4
0
6
0
7
1
1
6
7
9
3
6
1
8
2
9
5
4
6
0
1
6
5
6
8
2
1
7
1
2
3
6
1

Alloted
p[0][0] = 2
p[0][1] = 3
p[0][2] = 6
p[0][3] = 4
p[0][4] = 0
p[0][5] = 5
p[0][6] = 8
p[1][0] = 3
p[1][1] = 7
p[1][2] = 5
p[1][3] = 2
p[1][4] = 3
p[1][5] = 1
p[1][6] = 4
p[2][0] = 8
p[2][1] = 2
p[2][2] = 4
p[2][3] = 0
p[2][4] = 6
p[2][5] = 0
p[2][6] = 7
p[3][0] = 0
p[3][1] = 1
p[3][2] = 6
p[3][3] = 5
p[3][4] = 6
p[3][5] = 8
p[3][6] = 2
p[4][0] = 0
p[4][1] = 1
p[4][2] = 6
p[4][3] = 5
p[4][4] = 6
p[4][5] = 8
p[4][6] = 2
p[5][0] = 0
p[5][1] = 1
p[5][2] = 6
p[5][3] = 5
p[5][4] = 6
p[5][5] = 8
p[5][6] = 2
p[6][0] = 18431
p[6][1] = 14355
p[6][2] = 2048
p[6][3] = 18178
p[6][4] = 9471
p[6][5] = -9729
p[6][6] = 14357

There are two bold parts in above output
1st shows the acutal value stored, which is later displayed (as shwon in 2nd bold part), why does this happen.
Though the same code works for smaller number well.

Manish B
• 06-20-2008
tabstop
The value of p is not changed by the call to point. You would need another level of indirection (pass in &p, and a should then be an int ***).
• 06-20-2008
foxman
Plus there's another error in your point function (once you'll fix the first one, you'll need to fix that one too)
Code:

```void point(int **a,int row,int col) {   int i;     //printf ("\n%u\n",a);     a=(int **) malloc(sizeof(int *) * row);     if(a==NULL)   {       printf ("CAnnot allot space");       exit(1);   }     for(i=0;i<col;++i)  // Here, replace "col" to "row"   {       a[i]=(int *) malloc(sizeof(int) * col);       if(a[i]==NULL)       {         printf ("CAnnot allot space");         exit(1);       }   } }```
• 06-20-2008
The problem I see first off is this:
Code:

```  for(i=0;i<col;++i)   {       a[i]=(int *) malloc(sizeof(int) * col);       if(a[i]==NULL)       {         printf ("CAnnot allot space");         exit(1);       }   }```
In the above, i will never == 0, because it's incremented before the next line of code within the for loop, so a[0], will be ignored.

Also, a[i] will run outside the bounds of a[] by one when i == col - 1. At that point, i will
again be incremented prematurely, and will equal col, in your last time through the for
loop.

Use the standard idiom unless you have a specific reason not to. An example would be an
array where you want to work only with 1 through col - 1. In that case, just add "i < (col - 1)", and you'll be OK.

The standard idiom, is:
Code:

```for(i = 0; i < col; i++)  {   //your loop code, here }```
• 06-20-2008
laserlight
Quote:

In the above, i will never == 0, because it's incremented before the next line of code within the for loop, so a[0], will be ignored.
That does not sound correct. i will be 0 on the first iteration of the loop. The loop is identical to what you suggested, since pre-increment and post-increment have no net difference when used alone. In fact, in C++, the "standard idiom" is the original example, since your example could result in needless inefficiency if i was of a class type (but obviously this does not hold in C since there is no operator overloading).
• 06-20-2008
audinue
I suggest this little correction :)

Code:

```#include <stdio.h> #include <stdlib.h> //data: int a, &a == *a --> in a parameter of function if we want to modify 'a' //pointer to data: int *a, (&a == **a) //pointer to pointer to data: int **a, (&a == ***a) void point(int ***a, int rows, int cols) {   //int i; put this one below, little bit confusing with pascal style ^_^   //do not cast malloc (in C)   if((*a = malloc(sizeof(int *) * rows)) == NULL)       exit(EXIT_FAILURE); //avoid magic numbers...   int i;   for(i=0; i<rows; i++)   {       (*a)[i] = NULL;       if(((*a)[i] = malloc(sizeof(int) * cols)) == NULL) //i wonder... should we deallocate this?         exit(EXIT_FAILURE);   } } //prefer to use int instead of void, C is neither Java nor eC int main() {   int **p = NULL;   int rows = 7;   int cols = 7;     point(&p, rows, cols);   int i, j;     for(i=0; i<rows; i++)   {       for(j=0; j<cols; j++)       {         p[i][j] = rand(); //sorry, where i can find random function??       }   }     for(i=0; i<rows; i++)   {       for(j=0; j<cols; j++)       {         printf("&#37;d\n", p[i][j]);       }   }     free(p); //is it right? }```
• 06-20-2008
whiteflags
I further recommend returning an error code so that the caller has a chance to handle the error, and bail after any tidying. An unpoint function might also be handy.

It might look like this - I'm bored:
Code:

```int point (int *** a, int row, int col) {     if (row<1 || col<1) {         return -1; /* insufficient parameters */     }     *a = (int **) malloc(sizeof *a * row);     if (*a != NULL) {         int i;         for (i=0; i<row; ++i) { /* every row needs columns */             (*a)[i] = (int *) malloc(sizeof (*a)[i] * col);             if ((*a)[i] == NULL) {                 return -2;             }         }     }     else {         return -2; /* insufficient memory alloted */     }     return 0; /* success */ } void unpoint (int *** a, int row, int col) {     int i=row;     while (i-- > 0) {         free((*a)[i]);     }     free(*a);     *a=NULL; }```
• 06-20-2008
audinue
Thanks citizen, but why are you bored?
• 06-20-2008
mkruk
void main() *cough* ...

what is randomize(); supposed to be? the proper way to initialise the random number generator on C/C++ is srand()

also, it's rand(), not random().

I suppose both functions may work with a borland compiler (those are actually pascal/delphi commands, thus they might incorporate them), but it's better to stick to the standards, so consider using srand() and rand().
This will also make applications more portable.

I guess the other problems were already pointed out by the previous postings
• 06-20-2008
Salem
It's a lot easier to follow the semantics of malloc, and return an int** pointer, rather than pass "a pointer to" another pointer (and have to deal with all the extra notation involved).
• 06-20-2008
Quote:

Originally Posted by laserlight
That does not sound correct. i will be 0 on the first iteration of the loop. The loop is identical to what you suggested, since pre-increment and post-increment have no net difference when used alone. In fact, in C++, the "standard idiom" is the original example, since your example could result in needless inefficiency if i was of a class type (but obviously this does not hold in C since there is no operator overloading).

I can't help you with C++, but in C, i will never refer to the zeroth element of the array with pre-incrementing.

The increment is not used alone in this instance, so it's effect when used alone, is irrelevant.
• 06-20-2008
laserlight
Quote:

I can't help you with C++, but in C, i will never refer to the zeroth element of the array with pre-incrementing.

The increment is not used alone in this instance, so it's effect when used alone, is irrelevant.

Eh, it sounds like you misunderstand how for loops work. I suggest that you try out this program:
Code:

```#include <stdio.h> int main(void) {     int i;     for (i = 0; i < 10; ++i)     {         printf("&#37;d ", i);     }     printf("\n");     for (i = 0; i < 10; i++)     {         printf("%d ", i);     }     printf("\n");     return 0; }```
If what you say is true, the output will be:
Code:

```1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9```
I posit that what you say is false, and the output will be:
Code:

```0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9```
• 06-20-2008
swoopy
>I can't help you with C++, but in C, i will never refer to the zeroth element of the array with pre-incrementing.
Just to confirm what Lasarlight said, in a for-loop it makes no difference whether you use pre-increment or post-increment.
• 06-20-2008
C_ntua
There is a "nicer" way to allocate a 2d, 3d etc array. It has also the advantage that is mallocs one space of memory, so it will be more effective. And that it requires two lines of code :)
Code:

```int *array3d = malloc(X * Y * Z * sizeof(int)); #define array3d(x, y, z) array[(x) + (y * X) + (z * X * Y)]```
The only downside is that if you have a function that requires ***int you won't be able to pass array3d.
• 06-20-2008
You're both absolutely correct.

Thanks to you both. I have no idea where I was taught that, or taught it to myself.

Reminds me of the old joke:

A group of programmers at a conference, were asked "Imagine yourself on an airplane, and the stewardess announces over the intercom that today, your companies software will be flying the plane. How confident do you feel about flying now?"

All the programmers were immediately objecting and expressed serious doubts about this. All but one gentleman who appeared quite confident. When asked why he said:

"I'm not worried. My companies software would never get the jet to the runway, even."

:)
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last