I don't understand the following..

Discussion in 'C Programming' started by mt, Aug 4, 2011.

  1. mt

    mt Guest

    I am trying to understand the following code and I am having some
    problems..

    1. What is the meaning of double*** pdata? Why the need to declare a
    pointer to a pointer to a pointer?
    2. same thing for int*** pmask
    Please elucidate this for me.

    static int
    makedatamask(int nrows, int ncols, double*** pdata, int*** pmask)
    { int i;
    double** data;
    int** mask;
    data = malloc(nrows*sizeof(double*));
    if(!data) return 0;
    mask = malloc(nrows*sizeof(int*));
    if(!mask)
    { free(data);
    return 0;
    }
    for (i = 0; i < nrows; i++)
    { data = malloc(ncols*sizeof(double));
    if(!data) break;
    mask = malloc(ncols*sizeof(int));
    if(!mask)
    { free(data);
    break;
    }
    }
    if (i==nrows) /* break not encountered */
    { *pdata = data;
    *pmask = mask;
    return 1;
    }
    *pdata = NULL;
    *pmask = NULL;
    nrows = i;
    for (i = 0; i < nrows; i++)
    { free(data);
    free(mask);
    }
    free(data);
    free(mask);
    return 0;
    }
     
    mt, Aug 4, 2011
    #1
    1. Advertising

  2. mt

    Nobody Guest

    On Thu, 04 Aug 2011 12:48:26 -0700, mt wrote:

    > I am trying to understand the following code and I am having some
    > problems..
    >
    > 1. What is the meaning of double*** pdata?


    It means that pdata is a pointer to a pointer to a pointer to a double.

    > Why the need to declare a pointer to a pointer to a pointer?
    > 2. same thing for int*** pmask
    > Please elucidate this for me.


    The function allocates a pair of what are effectively two-dimensional
    arrays, in the sense that elements are accessed as data[row][col] and
    mask[row][col]. data[row][col] is a double, so data[row] is a pointer to
    double and data is a pointer to pointer to double.

    In order to return these pointers to the caller, the function accepts
    arguments which are pointers to where to store the pointers.
     
    Nobody, Aug 4, 2011
    #2
    1. Advertising

  3. mt <> wrote:
    > I am trying to understand the following code and I am having some
    > problems..


    > 1. What is the meaning of double*** pdata? Why the need to declare a
    > pointer to a pointer to a pointer?
    > 2. same thing for int*** pmask
    > Please elucidate this for me.


    > static int
    > makedatamask(int nrows, int ncols, double*** pdata, int*** pmask)
    > { int i;
    > double** data;
    > int** mask;
    > data = malloc(nrows*sizeof(double*));
    > if(!data) return 0;
    > mask = malloc(nrows*sizeof(int*));
    > if(!mask)
    > { free(data);
    > return 0;
    > }
    > for (i = 0; i < nrows; i++)
    > { data = malloc(ncols*sizeof(double));
    > if(!data) break;
    > mask = malloc(ncols*sizeof(int));
    > if(!mask)
    > { free(data);
    > break;
    > }
    > }
    > if (i==nrows) /* break not encountered */
    > { *pdata = data;
    > *pmask = mask;
    > return 1;
    > }


    <Further error handling snipped>

    Basically, what this code is meant to do is to create two arrays
    of pointers, with each of the pointers in the first array poin-
    ting to an array of doubles and in the second to an array of ints.
    (this could be e.g. an implementation of two matrices when using
    fixed sized, two-dimensional arrays won't do for whatever reasons).

    But the resulting pointers (to array of pointers), namely 'data'
    and 'mask' only exist in that function. How to return them to
    the caller? You can't pass their addresses back via the single
    return value, and the return value is used for error signaling
    anyway. Since passing arguments to functions in C is always by
    value, you can't pass the pointers you wan't to be set to the
    function - in that case all the function would get would be
    copies of those pointers and modifying them wouldn't change
    anything about the values the arguments have outside of the
    function. So the way to go is to pass two pointers to the
    pointers to the function that then get set within the function
    (to the values of 'data' and 'mask'). In the caller you thus
    would do something like

    double **a;
    int **b;

    makedatamask( numRows, numCols, &a, &b );

    I.e. 'a' and 'b' are, like 'data' and 'mask' in the function,
    pointers to pointers. And in order to allow modification of
    what 'a' and 'b' point to within the function a pointer to
    each of them gets passed. Thus you end up with a triple in-
    direction.

    There's actually no more to it then when you have to pass a
    simple integer to a function that is to be modified within
    the function. You could have (as contrived example)

    void set_a( int *a ) { *a = 17; }

    int x;
    set_a( &x );

    Now 'x' will be set to 17.

    The principle is exactly the same as in your case: in order
    to have 'x' modified in the function (and the change being
    visible in the caller) you need to pass a pointer to what
    you want to modify.

    The only thing that makes you're code a bit more "hairy" ist
    that you want to have something modified that is already a
    pointer to a pointer, thus you have to pass a pointer to a
    pointer to a pointer.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Aug 4, 2011
    #3
  4. mt

    John Gordon Guest

    In <> mt <> writes:

    > I am trying to understand the following code and I am having some
    > problems..


    > 1. What is the meaning of double*** pdata? Why the need to declare a
    > pointer to a pointer to a pointer?
    > 2. same thing for int*** pmask
    > Please elucidate this for me.


    In general, if you want to pass an object into a function and have the
    function change that object's value, you must pass a pointer-to-the-object
    instead of passing the object directly.

    For example, this won't work:

    void set_value_to_seven(int i)
    {
    i = 7;
    }

    int main(void)
    {
    int x = 5;
    set_value_to_seven(x);
    printf("x is now %d\n"); // will print "x is now 5"
    }

    However, this will work:

    void set_value_to_seven(int *i)
    {
    *i = 7;
    }

    int main(void)
    {
    int x = 5;
    set_value_to_seven(&x);
    printf("x is now %d\n"); // will print "x is now 7"
    }

    Along similar lines, if you want to pass a pointer into a function which
    malloc's space for the pointer, it won't work if you pass it directly:

    void allocate_ten_ints(int *i)
    {
    i = malloc(10 * sizeof(int));
    }

    int main(void)
    {
    int *x = NULL;
    allocate_ten_ints(x);
    x[0] = 5; // will crash because i is still NULL
    }

    But it will work if you pass a pointer-to-the-pointer:

    void allocate_ten_ints(int **i)
    {
    *i = malloc(10 * sizeof(int));
    }

    int main(void)
    {
    int *x = NULL;
    allocate_ten_ints(&x);
    x[0] = 5; // will work
    }

    Look closely at these lines in makedatamask:

    if (i==nrows) /* break not encountered */
    { *pdata = data;
    *pmask = mask;
    return 1;
    }
    *pdata = NULL;
    *pmask = NULL;

    This function wants to modify the value of pdata -- either by setting it
    to point to data, or by setting it point to NULL. Therefore the caller
    must pass a pointer-to-pdata. I'm assuming pdata is declared like this
    in makedatamask()'s caller function:

    double **pdata;

    Therefore, since the caller wants makedatamask to change pdata's value,
    it must pass a pointer-to-pdata, so makedatamask gets an argument of
    type "double ***".

    --
    John Gordon A is for Amy, who fell down the stairs
    B is for Basil, assaulted by bears
    -- Edward Gorey, "The Gashlycrumb Tinies"
     
    John Gordon, Aug 4, 2011
    #4
  5. mt

    Paul N Guest

    On Aug 4, 8:48 pm, mt <> wrote:
    > I am trying to understand the following code and I am having some
    > problems..
    >
    > 1. What is the meaning of double*** pdata? Why the need to declare a
    > pointer to a pointer to a pointer?


    Other people have answered this, but I'll have a go as well.

    Let's take it a bit at a time.

    > { data = malloc(ncols*sizeof(double));


    data points at some memory that stores ncols doubles. This memory
    is alloocated using malloc but we are treating it a bit like an array
    of doubles. So data has type double *.

    > data = malloc(nrows*sizeof(double*));


    We are also treating data like an array. It's an array of things like
    data. So data itself has a type of double **.

    > static int
    > makedatamask(int nrows, int ncols, double*** pdata, int*** pmask)

    ....
    > { *pdata = data;


    Here we want to pass the value of data out of the routine, as well as
    the value of mask. The function can only have one return value, and
    we're using that to say whether the function succeeded or not. So to
    pass the value of data out, we pass in a pointer telling the function
    where to put the value. That pointer is pdata, and as data has type
    double **, pdata has type double ***.

    Hope that helps...
    Paul.
     
    Paul N, Aug 10, 2011
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kenneth Lantrip

    I don't get the error with the following

    Kenneth Lantrip, Jul 18, 2004, in forum: C Programming
    Replies:
    4
    Views:
    289
    Mark McIntyre
    Jul 18, 2004
  2. Replies:
    7
    Views:
    272
  3. Replies:
    0
    Views:
    455
  4. sqlsurfing
    Replies:
    0
    Views:
    896
    sqlsurfing
    Jan 27, 2010
  5. Chad
    Replies:
    12
    Views:
    662
Loading...

Share This Page