A few days ago I stumbled on a code where an extensive use of conversions from pointer to type to pointer to array of type was made to give a bi-dimensional view of a linear vector in memory. A simple example of such a technique is reported below for clarity:
#include <stdio.h>
#include <stdlib.h>
void print_matrix(const unsigned int nrows, const unsigned int ncols, double (*A)[ncols]) {
// Here I can access memory using A[ii][jj]
// instead of A[ii*ncols + jj]
for(int ii = 0; ii < nrows; ii++) {
for(int jj = 0; jj < ncols; jj++)
printf("%4.4g",A[ii][jj]);
printf("\n");
}
}
int main() {
const unsigned int nrows = 10;
const unsigned int ncols = 20;
// Here I allocate a portion of memory to which I could access
// using linear indexing, i.e. A[ii]
double * A = NULL;
A = malloc(sizeof(double)*nrows*ncols);
for (int ii = 0; ii < ncols*nrows; ii++)
A[ii] = ii;
print_matrix(nrows,ncols,A);
printf("\n");
print_matrix(ncols,nrows,A);
free(A);
return 0;
}
Given that a pointer to type is not compatible with a pointer to array of type, I would like to ask if there are risks associated with this casting, or if I can assume that this casting will work as intended on any platform.
UPDATE: the strikethrough part is true, but irrelevant.
As I posted in the comment, the question is really whether in a two-dimensional array, the subarrays (rows) contain internal padding. There shall certainly be no padding inside each row, as the standard defines arrays to be contiguous. Also, the outer array shall introduce no padding. In fact, scanning through the C standard, I find no mention of padding in the context of arrays, so I interpret "contiguous" to mean that there's never any padding at the end of a subarray inside a multidimensional array. Since sizeof(array) / sizeof(array[0])
is guaranteed to return the number of elements in an array, there can be no such padding.
That means that the layout of a multidimensional array of nrows
rows and ncols
columns must be the same as that of an 1-d array of nrows * ncols
. So, to avoid the incompatible type error, you could do
void *A = malloc(sizeof(double[nrows][ncols]));
// check for NULL
double *T = A;
for (size_t i=0; i<nrows*ncols; i++)
T[i] = 0;
then pass to print_array
. This should avoid the potential pitfall of pointer aliasing; pointers of different types are not permitted to point into the same array unless at least one of them has type void*
, char*
or unsigned char*
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With