I have a one-dimensional array int *data
and I know the number of rows
and cols
which are effectively stored within it. That is, I can access an element of the two-dimensional matrix (i,j)
by using something like data[i*cols+j]
.
Specifically, these are stored in a struct:
typedef struct {
int *data;
int rows;
int cols;
} matrix_t;
At some point in the past, I also wrote this voodoo code:
#define MATRIXP(m) __typeof__(__typeof__(__typeof__(*((m).data))[(m).cols]) *)
#define MATRIXD(m) ((MATRIXP(m)) ((m).data))
With these definitions, I am able to do:
MATRIXP(matrix) m = MATRIXD(matrix);
And then I can use the matrix m
as a two-dimensional matrix pointer for accessing data
.
m[3][2] = 5; /* assign the element in row 3 and column 2 */
This is very nice and means I don't need to remember to always have an expression like data[i*cols+j]
. However, I wrote this code some time ago and I now cannot remember how it works.
Can someone please explain exactly how all those __typeof__
operators are working, and how to go about reading similar expressions? What is the type of the variable m
?
I know it expands to something like:
__typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) m = ((__typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *)) ((matrix).data));
Is this method of accessing data
safe? Is it the best way to do this?
Question 1:
MATRIXP(matrix) m
(matrix
should be a variable of type matrix_t
) will be expanded to
__typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) m
From in side to out side
__typeof__(*((matrix).data))
is the type of *((matrix).data)
, which is int
according to the definition of matrix_t
.
so (__typeof__(*((matrix).data))[(matrix).cols])
equals (int [cols])
so __typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *)
equals (int [cols] *)
and that is the type given by MATRIXP(matrix)
.
Therefore, MATRIXP(matrix)
equals (int [(matrix).cols] *)
. In other words,
MATRIXP(matrix) m
is effectively
int (*m)[matrix.cols]
As pointed out by @codebeard
Question 2:
It looks quite safe to me.