I was looking at the documentation for DMDAVecGetArray and was surprised that it could create a plain ordinary C array whose indices somehow ranged from, say, istart
to istart + size - 1
, rather than from 0 to size - 1
, or a multidimensional array (also an ordinary C array) whose indices ranged from istart
to istart + isize - 1
, jstart
to jstart + jsize - 1
, etc. I wasn't sure how that worked, so I looked into the code and found that DMDAVecGetArray uses the functions VecGetArray1d, VecGetArray2d, etc. behind the scenes to create these oddly indexed arrays. The code for VecGetArray1d looks like this:
PetscErrorCode VecGetArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
{
PetscInt N;
VecGetLocalSize(x,&N);
if (m != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local array size %D does not match 1d array dimensions %D",N,m);
VecGetArray(x,a);
*a -= mstart;
return(0);
}
At least superficially, this looks similar to the trick for doing 1-indexed arrays in C, that is,
int realarray[10];
int *array = &realarray[-1];
except that the pointer a
in the PETSc code above is directly decremented instead of having a second pointer variable like array
above.
Am I looking at what I think I'm looking at? I find it hard to believe that a well-used library code like PETSc would relying on undefined behavior, so I'm not sure if that PETSc code is really illegal.
What is actually going on?