Search code examples
carraysmatrixmultidimensional-arraytypeof

Accessing a one-dimensional array as a two-dimensional array


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.

  1. 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));
    
  2. Is this method of accessing data safe? Is it the best way to do this?


Solution

  • 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

    1. __typeof__(*((matrix).data)) is the type of *((matrix).data), which is int according to the definition of matrix_t.

    2. so (__typeof__(*((matrix).data))[(matrix).cols]) equals (int [cols])

    3. so __typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) equals (int [cols] *)

    4. 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.