I've been accessing N-dimensional arrays with one-dimensional pointers in C for decades now. But now, reading this other SO question, I learnt that's UB.
I feel quite disappointed to read that, to be honest, even if it works the way you'd expect in every compiler, but it's UB anyway.
One area where I find this most worrying is when writing serialization functions.
For example, let's assume you have several float
arrays such as:
float a[5];
float b[4][4];
float c[7][2][4][5];
According to the C specification, should I write three different functions if I want to serialize these three arrays?
The following function (which is the way I'd do this), is UB according to the question above:
void serializeNfloatarray(FILE *stream, float *ptr, size_t ndims, size_t *dims) {
size_t numitems=1;
if(ndims==0) return;
fprintf(stream, "%zu ", ndims);
for(size_t f=0; f<ndims; f++) {
fprintf(stream, "%zu ", dims[f]);
numitems *= dims[f];
}
for(size_t i=0; i<numitems; i++)
fprintf(stream,"%f ", ptr[i]); /* <- UB !!! */
}
Is it impossible to write one C function valid for all types of float arrays without going into UB?
char
pointer back to anint
pointer, and that's UB. You can do the access only with thechar
pointer, not theint
pointer. – Eckartfloat *
forces you to explicitly cast to(float *)
by the caller in case of multidimensional arrays. If this is what you want, that is fine. Otherwise, you probably have to change the argument tovoid *
to hush the compiler, but that would obviously be slightly susceptible to human error. – Phiona