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

[netCDF #EAM-622298]: Missing: "unsigned long"



> Hi Tony,
> 
> > We have noticed that netCDF4 does not support the "unsigned long" datatype.
> >
> > The netCDF api supports the following:
> > int nc_put_var_text  (int ncid, int varid, const char *tp);
> > int nc_put_var_uchar (int ncid, int varid, const unsigned char *up);
> > int nc_put_var_schar (int ncid, int varid, const signed char *cp);
> > int nc_put_var_short (int ncid, int varid, const short *sp);
> > int nc_put_var_int   (int ncid, int varid, const int *ip);
> > int nc_put_var_long  (int ncid, int varid, const long *lp);
> > int nc_put_var_float (int ncid, int varid, const float *fp);
> > int nc_put_var_double(int ncid, int varid, const double *dp);
> > int nc_put_var_ubyte (int ncid, int varid, const unsigned char *op);
> > int nc_put_var_ushort(int ncid, int varid, const unsigned short *op);
> > int nc_put_var_uint  (int ncid, int varid, const unsigned int *op);
> > int nc_put_var_longlong (int ncid, int varid, const long long *op);
> > int nc_put_var_ulonglong(int ncid, int varid, const unsigned long
> > long *op);
> > int nc_put_var_string(int ncid, int varid, const char **op);
> > int nc_put_var       (int ncid, int varid,  const void *op);
> >
> > This list excludes the "unsigned long" datatype.  Is there a reason for
> > this?  We would like to know this reason.  We want to avoid using the
> > int datatype since we have found int to be implementation-defined: int
> > is either 16 or 32 bits depending on the platform.
> 
> It looks like an oversight, and I'm surprised no one else has noticed it
> or commented on it.  Thanks for pointing out this gap.  I'll see if it's
> something we can fix in the C interface before the 4.1 release, but it may
> be too late, in which case it will be in a subsequent dot release.
> 
> --Russ

This is a feature, not a bug!

The NC_LONG type is not a proper netCDF type at all. In fact, it is just the 
NC_INT type. From the netcdf.h file:
/*                                                                              
                                                                                
                 
 * If and when 64 integer types become ubiquitous,                              
                                                                                
                 
 * we would like to use NC_LONG for that.                                       
                                                                                
                 
 * For now, define for backward compatibility.                                  
                                                                                
                 
 */
#define NC_LONG NC_INT

This was based on the idea that C compilers would someday provide a 64-bit 
"int" type. That is, the meaning of "int" would change to a 64-bit, instead of 
a 32-bit integer, as is the case with most C compilers today. This may still 
happen. But it seems unlikely to me. The "long long" type is used for 64-bit 
integers, and that's part of ANSO I C too. (Of course, one could just respond 
that the standard does not actually specify that long long is 64-bits, just 
that it's twice the size of an "int".) 

In theory (say the C purists), all the worlds C compilers could switch to 
64-bit someday, and all the existing code would still work. This may be true 
for some code, but not for I/O code, since changing the C standard does not 
change how many bits are used in disk archives. If such a change to C 
implementations were to take place, then the use of NC_LONG would seriously 
break backward compatibility for netCDF files. All existing NC_LONG data would 
become unreadable as "long" ints, any program that used NC_LONG or any of the 
nc_put|get_var*_long functions would find that their code was badly broken when 
they changed C compilers. (I believe *all* the int read/write functions of 
netCDF would break in such a case.)

In netCDF-4, the new 64-bit int types are supported with calls like this:

EXTERNL int
nc_put_att_longlong(int ncid, int varid, const char *name, nc_type xtype,
                 size_t len, const long long *op);

EXTERNL int
nc_get_att_longlong(int ncid, int varid, const char *name, long long *ip);

etc.

As types, netcdf-4 uses the unambiguous NC_INT64 and NC_UINT64.

In fact, support for NC_LONG, required from netCDF-4 for backward 
compatibility, cost me considerable trouble. The problem is that the long type 
may be the same as an int (and this is the usual case), or it may be the same 
as a "long long." This is a real bummer, but if it wasn't hard they wouldn't 
need someone like me to program it, I guess. ;-)

In summary then, there is no NC_ULONG and never shall be, because that would 
just add confusion to the API and implementation. Users should use NC_UINT for 
32-bit unsigned ints, and NC_UINT64 for 64-bit unsigned ints. NC_LONG is 
supported only for backward compatibility reasons.

Thanks,

Ed



Ticket Details
===================
Ticket ID: EAM-622298
Department: Support netCDF
Priority: Normal
Status: Closed