Reputation: 592
I have an array with x * x elements defined as a pointer.
I wanted to do something like this:
void func(const unsigned int x, const int *flat_array)
{
const int (*reshaped)[x] = flat_array;
...
}
but how?
Upvotes: 0
Views: 3358
Reputation: 214920
Assuming that the pointer does point at an array, that is - a chunk of adjacent items of the same type, then you can safely cast the pointer type:
const int (*reshaped)[x] = (const int(*)[x])flat_array;
This is guaranteed to work because the type aliasing rules in C are only concerned of the nature of the pointed-at data and not so much about the pointer types involved. (See the concept of effective type, 6.5/6).
Upvotes: 0
Reputation: 754920
This code works for me. Note that it uses a C99 (and C11) variable length array (VLA). It won't compile with a C89/C90 compiler.
#include <stdio.h>
static void func(const unsigned int x, const int *flat_array)
{
const int (*reshaped)[x] = (void *)flat_array;
for (unsigned int i = 0; i < x; i++)
{
for (unsigned int j = 0; j < x; j++)
printf("%3d", reshaped[i][j]);
putchar('\n');
}
}
int main(void)
{
int flat[] =
{
/* random -n 25 10 99 | commalist -n 5 -b ' ' */
73, 34, 76, 48, 17,
25, 71, 11, 87, 74,
18, 87, 11, 47, 32,
33, 62, 41, 55, 90,
90, 28, 69, 58, 29,
};
for (int i = 0; i < 5; i++)
{
printf("R[%d]", i);
for (int j = 0; j < 5; j++)
printf(" [%d] = %2d", j, flat[i * 5 + j]);
putchar('\n');
}
func(5, flat);
return 0;
}
Compiled without warnings on a Mac running macOS Sierra 10.12.6 using GCC 7.1.0 with the compilation options:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
-Wstrict-prototypes rs37.c -o rs37
$
Without the cast (to void *
) in the function, I get the error:
initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
The void *
cast is an effective way to deal with the problem — but it could be misused very easily. You could also write:
const int (*reshaped)[x] = (int (*)[x])flat_array;
That explicitly casts direct to the correct type — pointer to array of integers of row width x
. You could add a const
into the cast if you wanted to.
Output:
R[0] [0] = 73 [1] = 34 [2] = 76 [3] = 48 [4] = 17
R[1] [0] = 25 [1] = 71 [2] = 11 [3] = 87 [4] = 74
R[2] [0] = 18 [1] = 87 [2] = 11 [3] = 47 [4] = 32
R[3] [0] = 33 [1] = 62 [2] = 41 [3] = 55 [4] = 90
R[4] [0] = 90 [1] = 28 [2] = 69 [3] = 58 [4] = 29
73 34 76 48 17
25 71 11 87 74
18 87 11 47 32
33 62 41 55 90
90 28 69 58 29
Upvotes: 3
Reputation: 68004
if original was malloced and I understand what reshape means
#define MIN(x,y) ((x) > (y) ? (y) : (x))
int *reshape(int *src, int srcRows, int srcCols, int newRows, int newColums)
{
int *newarray = (*src != NULL && newRows > 0 && newColums > 0) ? malloc(newRows * newColums) : NULL;
if (newarray != NULL)
{
for (int row = 0; row < MIN(srcRows, newRows); row++)
for (int col = 0; col < MIN(srcCols, newColums); col++)
*(newarray + row * newColums + col) = *(src + row * srcCols + col);
free(src);
}
return newarray;
}
If new array is smaller some data will be lost.
Upvotes: 0
Reputation: 2063
this should do it :
int m,n;
typedef int myarray_t[x][x];
myarray_t *myarray;
myarray = (myarray_t *) flat_array;
for (m=0;m<x;m++)
for (n=0;n<x;n++)
printf("[%d][%d] : %d\n",m,n,(*myarray)[m][n]);
Upvotes: 0