指针与多维数组
多维数组在内存中按行优先连续存储。指向多维数组的指针需要正确理解其类型——int (*p)[N] 指向包含 N 个 int 的数组,与 int *p[N](指针数组)完全不同。
二维数组的指针
int mat[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
/* mat 的类型:int (*)[4] */
/* mat[i] 的类型:int * */
int (*p)[4] = mat; /* p 指向包含 4 个 int 的数组 */
printf("%d\n", (*p)[0]); /* 1:第一行第一列 */
printf("%d\n", p[1][2]); /* 7:第二行第三列 */
p++; /* p 指向下一行(移动 4 * sizeof(int) 字节) */
printf("%d\n", (*p)[0]); /* 5 */
数组指针 vs 指针数组
int (*p)[4]; /* 数组指针:p 是指针,指向 int[4] 数组 */
int *q[4]; /* 指针数组:q 是数组,包含 4 个 int* */
/* 大小 */
printf("%zu\n", sizeof(p)); /* 指针大小 */
printf("%zu\n", sizeof(q)); /* 4 * sizeof(int*) */
作为函数参数
void print(int mat[][4], int rows) /* 等价于 int (*mat)[4] */
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
动态二维数组
/* 指针数组方式 */
int **create_matrix(int rows, int cols)
{
int **mat = malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++)
mat[i] = malloc(cols * sizeof(int));
return mat;
}
/* 连续内存方式 */
int *create_matrix_flat(int rows, int cols)
{
return malloc(rows * cols * sizeof(int));
}
/* 访问:mat[i * cols + j] */
常见错误
类型混淆:
int mat[3][4];
int **p = mat; /* 错误:类型不匹配 */
/* 正确 */
int (*p)[4] = mat;
维度省略:
void func(int mat[][]); /* 错误:除第一维外必须指定 */
void func(int mat[][4]); /* 正确 */
最佳实践
- 理解
int (*p)[N]和int *p[N]的区别 - 二维数组参数中,除第一维外都显式指定
- 动态二维数组考虑连续内存方式(缓存友好)
- 复杂矩阵运算使用专业库