Passing a pointer to pointer as a multi-dimensional array

Discussion in 'C Programming' started by entitledX, Jan 11, 2006.

  1. entitledX

    entitledX Guest

    Hi, I'm trying to use the HDF library to read a few HDF files that I
    need to process. The data in each file varies in rows, but the
    columns remain constant. Because of that, I had dynamically allocated
    a set of
    pointer to pointers as my multi-dimensional arrays. Here is my code (i
    have omitted checking calloc's return value to make this shorter):

    int **filter;
    filter = calloc( ylength, sizeof(int*) );
    for( i = 0 ; i < ylength ; i++ )
    filter = calloc( xlength, sizeof(int*) );

    The problem is that the function I have to use SDreaddata works fine if
    I declare filter as an actual multi-dimensional array: int
    filter[ylength][xlength]; However, I keep getting segmentation fault
    errors.
    SDreaddata is declared as:

    intn SDreaddata
    (int32 sdsid, int32 *start, int32 *stride, int32 *end, void *
    data);

    data is the parameter I am trying to pass filter to.
    Is there a way of passing filter into this function, somehow? Thanks in
    advance.
    entitledX, Jan 11, 2006
    #1
    1. Advertising

  2. entitledX <> wrote:

    > int **filter;
    > filter = calloc( ylength, sizeof(int*) );
    > for( i = 0 ; i < ylength ; i++ )
    > filter = calloc( xlength, sizeof(int*) );


    That inner calloc call should be sizeof(int), or better sizeof(
    *filter ). The possible size difference between int and int* may
    be part of your problem.

    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
    Christopher Benson-Manica, Jan 11, 2006
    #2
    1. Advertising

  3. entitledX

    Eric Sosman Guest

    entitledX wrote On 01/11/06 11:58,:
    > Hi, I'm trying to use the HDF library to read a few HDF files that I
    > need to process. The data in each file varies in rows, but the
    > columns remain constant. Because of that, I had dynamically allocated
    > a set of
    > pointer to pointers as my multi-dimensional arrays. Here is my code (i
    > have omitted checking calloc's return value to make this shorter):
    >
    > int **filter;
    > filter = calloc( ylength, sizeof(int*) );
    > for( i = 0 ; i < ylength ; i++ )
    > filter = calloc( xlength, sizeof(int*) );
    >
    > The problem is that the function I have to use SDreaddata works fine if
    > I declare filter as an actual multi-dimensional array: int
    > filter[ylength][xlength]; However, I keep getting segmentation fault
    > errors.
    > SDreaddata is declared as:
    >
    > intn SDreaddata
    > (int32 sdsid, int32 *start, int32 *stride, int32 *end, void *
    > data);
    >
    > data is the parameter I am trying to pass filter to.
    > Is there a way of passing filter into this function, somehow? Thanks in
    > advance.


    Study Questions 6.18 through 6.20 in the comp.lang.c
    Frequently Asked Questions (FAQ) list at

    http://c-faq.com/

    .... and ask again if you're still perplexed. Arrays of
    pointers (what you've created) are not the same as arrays
    of arrays (which SDreaddata() appears to require).

    --
    Eric Sosman, Jan 11, 2006
    #3
  4. "entitledX" <> writes:
    > Hi, I'm trying to use the HDF library to read a few HDF files that I
    > need to process. The data in each file varies in rows, but the
    > columns remain constant. Because of that, I had dynamically allocated
    > a set of
    > pointer to pointers as my multi-dimensional arrays. Here is my code (i
    > have omitted checking calloc's return value to make this shorter):
    >
    > int **filter;
    > filter = calloc( ylength, sizeof(int*) );
    > for( i = 0 ; i < ylength ; i++ )
    > filter = calloc( xlength, sizeof(int*) );


    Don't bother using calloc() for the first allocation. The differences
    between calloc() and malloc() are that calloc() takes two arguments to
    specify the size, and calloc() zeros the allocated space. For the
    first, you can just use malloc() and do the multiplication yourself.
    For the second, it doesn't do you any good here; all-bits-zero isn't
    necessarily a useful value for an int* (it *might* be a null pointer,
    but that's not guaranteed), and you re-assign values to all the
    elements anyway.

    The recommended form for the first allocation is:
    filter = malloc(ylength * sizeof *filter);
    or, if you prefer:
    filter = malloc(ylength * sizeof(*filter));

    Whether calloc() makes sense for the second allocation is another
    question. All-bits-zero is guranteed to be a representation of 0 for
    an integer type (the standard doesn't say so, but the committee has
    ruled on it). And of course you want sizeof(int), not sizeof(int*).

    > The problem is that the function I have to use SDreaddata works fine if
    > I declare filter as an actual multi-dimensional array: int
    > filter[ylength][xlength]; However, I keep getting segmentation fault
    > errors.
    > SDreaddata is declared as:
    >
    > intn SDreaddata
    > (int32 sdsid, int32 *start, int32 *stride, int32 *end, void *
    > data);
    >
    > data is the parameter I am trying to pass filter to.
    > Is there a way of passing filter into this function, somehow? Thanks in
    > advance.


    You're creating an array of pointers to arrays of int. Each row is
    allocated separately. The SDreaddata() function appears to expect a
    pointer to a *contiguous* array of int32, which it treats as a
    2-dimensional array. Since C doesn't support dynamically sized
    2-dimensional arrays very well, you have to specify the stride (the
    number of elements in each row).

    I'm not certain of this, since we can't see what SDreaddata() actually
    does with its parameters, but it certainly doesn't expect a
    pointer-to-pointer-to-int.

    Read section 6 of the C FAQ.

    Also, you need to make sure the element type is consistent. You're
    allocating arrays of int, but SDreaddata() uses int32 (that's not a
    standard type; presumably it's a typedef for some 32-bit type). Type
    int isn't necessarily 32 bits. If SDreaddata() expects int32, you
    need to use int32 yourself.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 11, 2006
    #4
  5. entitledX

    Old Wolf Guest

    entitledX wrote:

    > Hi, I'm trying to use the HDF library to read a few HDF files that I
    > need to process. The data in each file varies in rows, but the
    > columns remain constant. Because of that, I had dynamically
    > allocated a set of pointer to pointers as my multi-dimensional
    > arrays.


    > intn SDreaddata (int32 sdsid,
    > int32 *start, int32 *stride, int32 *end, void * data);
    >
    > data is the parameter I am trying to pass filter to.


    Clearly, this function expects 'data' to be a contiguous bunch
    of int32's. So you will have to allocate 'filter' in a contiguous
    fashion.

    (A pedantic point: the existing SDreaddata function will
    cause undefined behaviour when it converts the (void *)
    to (int *) because the value came from an int (*)[N]. But
    this will work on any system I've ever heard of).

    If your 'xlength' and 'ylength' variables are not known at
    compile-time, then your only option is to allocate a 1-D
    array for filter:

    int32 *filter = calloc( xlength * ylength, sizeof *filter );

    and then if you want to access it then you'll have to write
    out your multiplications or use a macro, eg.

    #define FILTER(X,Y) filter[(Y) * xlength + (X)]

    However, if the number of columns is known at compiletime
    (and if it is I suggest you use an upper-case identifier
    for it), you can malloc a 2-D array:

    int32 (*filter)[XLENGTH] = malloc( ylength * sizeof *filter );

    and this array can be accessed as filter[x][y], and can
    also be safely passed to SDreaddata(), with the same
    pedantic caveat as I mentioned above.

    If you have the option of modifying SDreaddata() to take
    an (int *) instead of a (void *), then please do so. Then
    pass *filter instead of filter in your version and in my
    second version.
    Old Wolf, Jan 12, 2006
    #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. Venkat
    Replies:
    4
    Views:
    961
    Venkat
    Dec 5, 2003
  2. truckaxle
    Replies:
    11
    Views:
    549
    Dave Thompson
    Jul 25, 2005
  3. Bernd Gaertner
    Replies:
    5
    Views:
    441
    Bernd Gaertner
    Nov 13, 2007
  4. Olumide
    Replies:
    6
    Views:
    737
    John Bode
    May 17, 2010
  5. Wirianto Djunaidi
    Replies:
    2
    Views:
    194
    Wirianto Djunaidi
    Apr 29, 2008
Loading...

Share This Page