NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[netCDF #OPV-437501]: Reading 2D array in C, into array of pointers



Hi Tiago,

Sorry to have taken so long to respond to your question ...

> I am a great fan of NetCDF and used it extensively with the Fortran and
> Python interfaces, but now I must work with it in C. (This question may
> be related to my ignorance in C.)

The main difference is that Fortran uses column-major ordering (first
inde3x varies fastest), but C uses row-major (last index varies
fastest).

> I have a NetCDF file with a 4D variable. I would like to read a 2D slice
> of that variable into a (double **) array, called 'mm' and defined as:
> 
> m = (double *) calloc(N * M, typeSize);
> mm = (double **) malloc(N* pointerSize);
> 
> for(i=0; i< N; i++, mm += M)
> mm[i] = m;
> 
> I know I can't read a 2D slice into it all at once because it is not
> contiguous.

It looks like it *is* contiguous, because you have allocated all N*M
doubles with a single call to calloc().  Then you have made m[1] point
to the ith row of doubles, but if you print out check the addresses,
you should be able to verify that mm[1][0] is the next double in
memory after mm[0][M-1], and in general the double mm[j+1][0]
immediately follows mm[j][M-1] in memory for any j in {0, 1, ...,
N-1}.

So you should be able to read a 2D slice into m, which is the same
as &m[0], which is the same as &mm[0][0].

>  ... So I'm trying to read one column at once with nc_get_vara:
> 
> 
> for (i=0, i<N, i++){
> nc_get_vara_double(ncid,varid,start,count,mm[i]);
> start[0]++;
> }

I assume you have declared start and count as arrays of size 4
(because you are reading a 4D netCDF variable).  I also assume you
have set 
  count[0] = M;
  count[1] = count[2] = count[3] = 1;
and that the netCDF variable you are trying to read would have a CDL
declaration something like
  double var(N, M, P, R);
with N and M the first two dimensions, used for "row" and "column".
If that's true, then the code above should read M values into the ith
row of the mm array, each time it's called.

> This compiles and when running it reads the first element of each row
> (i.e. mm[*][0]), but seems to put rubbish in all the other elements,
> which give a segfault when I try to access them. How do I read a 2D
> slice into a (double **) variable? I thought this would work as mm[i]
> is a pointer to a (double *) array. In the call to nc_get_vara_double
> I also tried putting &mm[i][0], but the result is the same...

If the assumptions I've spelled out above are correct, then this
should have worked, so I assume something is different, such as the
values of count.

> I can read the array using the uglier method of nc_get_var1_double in
> a M,N loop, but was looking for something more elegant and with less
> overhead.

Just reading in the whole 2D slice should be possible and is the most
elegant.  You shouldn't have to read in each element separately!

--Russ

Russ Rew                                         UCAR Unidata Program
address@hidden                      http://www.unidata.ucar.edu



Ticket Details
===================
Ticket ID: OPV-437501
Department: Support netCDF
Priority: Normal
Status: Closed