访问一维数组作为二维数组

10

我有一个一维数组int *data,我知道在其中实际存储了rowscols的数量。也就是说,我可以使用data[i*cols+j]来访问二维矩阵中的元素(i,j)

具体来说,这些数据被存储在一个结构体中:

typedef struct {
    int *data;
    int rows;
    int cols;
} matrix_t;

在过去的某个时间点,我也写过这段巫术代码:

#define MATRIXP(m) __typeof__(__typeof__(__typeof__(*((m).data))[(m).cols]) *)
#define MATRIXD(m) ((MATRIXP(m)) ((m).data))

有了这些定义,我能做到:

MATRIXP(matrix) m = MATRIXD(matrix);

然后我可以使用矩阵m作为一个二维矩阵指针来访问data

m[3][2] = 5; /* assign the element in row 3 and column 2 */

这很好,意味着我不需要记住总是要使用类似于data[i*cols+j]的表达式。然而,我之前写了这段代码,现在我想不起来它是如何工作的。

  1. 有人可以解释一下所有那些__typeof__运算符是如何工作的,以及如何阅读类似的表达式吗?变量m的类型是什么?

    我知道它会扩展成类似于:

__typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) m = ((__typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *)) ((matrix).data));
  • 访问数据的这种方法安全吗?这是最好的方式吗?


  • 1
    +1,但是您知道c99及更高版本允许您为多维数组分配连续的内存,例如int (*data)[cols] = malloc(sizeof(int[rows][cols]));。我的意思是,您所做的很好,但似乎有更好的方法。 - Dabo
    1
    在 C99 之前,你仍然可以使用 int(*data)[cols] = malloc(sizeof(int)*rows*cols); - Lundin
    你不能在结构体定义中放置像 int (*data)[cols] 这样的字段。我并不是真正询问如何在使用它的同一作用域中分配这样的东西。我需要能够将其传递给其他函数并轻松访问它。 - codebeard
    1个回答

    5

    问题1:

    MATRIXP(matrix) m (matrix 应该是一个 matrix_t 类型的变量) 将被展开为

    __typeof__(__typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) m
    

    从内部到外部

    1. __typeof__(*((matrix).data))*((matrix).data) 的类型,根据 matrix_t 的定义,它是 int 类型。

    2. 因此,(__typeof__(*((matrix).data))[(matrix).cols]) 等于 (int [cols])

    3. 所以 __typeof__(__typeof__(*((matrix).data))[(matrix).cols]) *) 等于 (int [cols] *)

    4. 这就是由 MATRIXP(matrix) 给出的类型。

    因此,MATRIXP(matrix) 等于 (int [(matrix).cols] *)。换句话说,

    MATRIXP(matrix) m
    

    实际上是

    int (*m)[matrix.cols]
    

    正如@codebeard所指出的那样

    问题2:

    在我看来,它看起来非常安全。


    1
    谢谢你的回答。所以 MATRIXP(matrix) m 实际上是 int (*m)[matrix.cols]?为什么这会在堆栈上导致大量分配? - codebeard
    @codebeard 噢,不会的。我的错误,回答已更新。谢谢你指出来。 - Lee Duhem
    我觉得让我感到困惑的部分是,虽然__typeof(int *)__ xint *x是相同的,但__typeof(int [5] *)__ x不是int [5] *x,而是int (*x)[5],对于为什么会这样并不完全清楚。 - codebeard
    1
    @codebeard __typeof 是原因。__typeof(int [5]) 是一个包含五个 int 的数组类型,然而,int [5] 不是一个有效的 C 类型,所以你不能像这样定义一个指向该类型的指针 int [5] *x,而必须使用 int (*x)[5]。还要注意,__typeof(int [5] *) 是无效的,你必须将其写成 __typeof(__typeof(int [5]) *) - Lee Duhem

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接