Thread: Dynamic 2 Dimensional Array

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    1

    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

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    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 ***).

  3. #3
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    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);
          }
       }
    }
    I hate real numbers.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    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
    }
    Last edited by Adak; 06-20-2008 at 11:59 AM.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    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).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    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?
    }
    Last edited by audinue; 06-20-2008 at 12:11 PM.

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    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;
    }
    Last edited by whiteflags; 06-20-2008 at 12:29 PM.

  8. #8
    Ugly C Lover audinue's Avatar
    Join Date
    Jun 2008
    Location
    Indonesia
    Posts
    489
    Thanks citizen, but why are you bored?

  9. #9
    FOSS Enthusiast
    Join Date
    Jun 2008
    Posts
    64
    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

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    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).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by laserlight View Post
    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.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by Adak
    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
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >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.

  14. #14
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    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.

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    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."


Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic Array Allocation function
    By P4R4N01D in forum C++ Programming
    Replies: 6
    Last Post: 05-15-2009, 02:04 AM
  2. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  3. Dynamic Mutli dimensional Array question.
    By fatdunky in forum C Programming
    Replies: 6
    Last Post: 02-22-2006, 07:07 PM
  4. Dynamic 2 dimensional array with new?
    By Quantum1024 in forum C++ Programming
    Replies: 10
    Last Post: 11-19-2005, 02:46 PM
  5. total size of dynamic memory allocated array
    By trekker in forum C Programming
    Replies: 10
    Last Post: 03-10-2002, 12:59 PM