Passing a pointer to pointer as a multi-dimensional array

E

entitledX

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.
 
C

Christopher Benson-Manica

entitledX said:
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.
 
E

Eric Sosman

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).
 
K

Keith Thompson

entitledX said:
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.
 
O

Old Wolf

entitledX said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top