二维动态数组指针访问
Two-dimensional dynamic array pointer access
p = (int *)malloc(m * n * sizeof(int));
如果我使用p
作为二维动态数组,如何访问里面的元素?
我假设 m 是列数,n 是行数(您可以使用 n 而不是 m在我的回答中是否相反)。
为了访问二维数组,您需要 2 个索引 - 我们称它们为 x
和 y
:
x
索引将在 0 .. m-1 和
范围内
y
索引将在 0 .. n-1
范围内
您可以通过以下方式计算 p
数组的索引:
int p_idx = y * m + x
然后您可以访问您的数组元素,例如这样:
p[p_idx] = 111; // set an element value
int a = p[p_idx]; // get an element value
您不能将 p
用作 two-dimensional 数组。它是一个整数指针。 Two-dimensional(动态分配)意味着嵌套指针。但是,您可以 表示 一个“扁平”形式的 two-dimensional 数组。下面是一些可能提供有用解释的代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
// Populating a 10x5 matrix
int m = 10;
int n = 5;
int* p = (int*) malloc(m*n*sizeof(int));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// Each row has n elements; to get the
// "flattened" index, treating the MxN
// matrix as row-major ordered (reading
// left-to-right, and THEN down the rows):
int flattened_index = (i * n) + j;
// E.g., populate with multiplication table data
p[flattened_index] = (i + 1) * (j + 1);
printf("%d\t", p[flattened_index]);
}
printf("\n");
}
// Inversely, to convert a flattened index to a
// row and column, you have to use modulus
// arithmetic
int flattened_index = 21;
int row = flattened_index / n; // Rounded-down integer division
int column = flattened_index % n; // Remainder after division
printf("%d * %d = %d\n", row + 1, column + 1, p[flattened_index]);
return 0;
}
这输出:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
6 12 18 24 30
7 14 21 28 35
8 16 24 32 40
9 18 27 36 45
10 20 30 40 50
5 * 2 = 10
如果您可以依靠您的 C 实现来支持 variable-length 数组(一项可选功能),那么一个很好的方法是将 p
声明为指向 (variable-length) 数组而不是指向 int
:
的指针
int (*p)[n] = malloc(m * sizeof(*p)); // m rows, n columns
然后你使用普通的双索引访问元素,就像你声明了一个普通的二维数组一样:
p[0][0] = 1;
p[m-1][n-1] = 42;
int q = p[2][1];
最广泛使用的 C 实现支持 VLA,但 Microsoft 的是一个明显的例外。
您实际上是在创建一个 single-dimensional 数组。但是,考虑到 C 中多维数组的事实,例如 int mat[m][n],我们仍然可以使用它来保存矩阵,它本身存储在连续的内存中。
#include <iostream>
int main()
{
int m, n;
std::cin >> m >> n;
int* mat_ptr = (int*)malloc(m * n * sizeof(int));
if (mat_ptr)
{
for (int row = 0; row < m; ++row)
{
for (int col = 0; col < n; ++col)
{
*(mat_ptr + ((row * n) + col)) = (row * n) + col;
}
}
for (int row = 0; row < m; ++row)
{
for (int col = 0; col < n; ++col)
{
std::cout << *(mat_ptr + ((row * n) + col)) << " ";
}
std::cout << std::endl;
}
}
return 0;
}
我个人更喜欢使用 wohlstad 的方法,但您也可以 variably-modified 类型,这是 C11 的可选功能,but will probably be mandated in C2x:
int (*p)[m] = malloc(n * sizeof *p);
这现在可以像普通二维数组一样使用,具有自动存储持续时间。
int n = 12, m = 9;
int (*p)[m] = malloc(n * sizeof *p);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
p[i][j] = i * m + j;
printf("%d\n", p[4][2]);
free(p);
p = (int *)malloc(m * n * sizeof(int));
如果我使用p
作为二维动态数组,如何访问里面的元素?
我假设 m 是列数,n 是行数(您可以使用 n 而不是 m在我的回答中是否相反)。
为了访问二维数组,您需要 2 个索引 - 我们称它们为 x
和 y
:
x
索引将在 0 .. m-1 和
范围内
y
索引将在 0 .. n-1
您可以通过以下方式计算 p
数组的索引:
int p_idx = y * m + x
然后您可以访问您的数组元素,例如这样:
p[p_idx] = 111; // set an element value
int a = p[p_idx]; // get an element value
您不能将 p
用作 two-dimensional 数组。它是一个整数指针。 Two-dimensional(动态分配)意味着嵌套指针。但是,您可以 表示 一个“扁平”形式的 two-dimensional 数组。下面是一些可能提供有用解释的代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
// Populating a 10x5 matrix
int m = 10;
int n = 5;
int* p = (int*) malloc(m*n*sizeof(int));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// Each row has n elements; to get the
// "flattened" index, treating the MxN
// matrix as row-major ordered (reading
// left-to-right, and THEN down the rows):
int flattened_index = (i * n) + j;
// E.g., populate with multiplication table data
p[flattened_index] = (i + 1) * (j + 1);
printf("%d\t", p[flattened_index]);
}
printf("\n");
}
// Inversely, to convert a flattened index to a
// row and column, you have to use modulus
// arithmetic
int flattened_index = 21;
int row = flattened_index / n; // Rounded-down integer division
int column = flattened_index % n; // Remainder after division
printf("%d * %d = %d\n", row + 1, column + 1, p[flattened_index]);
return 0;
}
这输出:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
6 12 18 24 30
7 14 21 28 35
8 16 24 32 40
9 18 27 36 45
10 20 30 40 50
5 * 2 = 10
如果您可以依靠您的 C 实现来支持 variable-length 数组(一项可选功能),那么一个很好的方法是将 p
声明为指向 (variable-length) 数组而不是指向 int
:
int (*p)[n] = malloc(m * sizeof(*p)); // m rows, n columns
然后你使用普通的双索引访问元素,就像你声明了一个普通的二维数组一样:
p[0][0] = 1;
p[m-1][n-1] = 42;
int q = p[2][1];
最广泛使用的 C 实现支持 VLA,但 Microsoft 的是一个明显的例外。
您实际上是在创建一个 single-dimensional 数组。但是,考虑到 C 中多维数组的事实,例如 int mat[m][n],我们仍然可以使用它来保存矩阵,它本身存储在连续的内存中。
#include <iostream>
int main()
{
int m, n;
std::cin >> m >> n;
int* mat_ptr = (int*)malloc(m * n * sizeof(int));
if (mat_ptr)
{
for (int row = 0; row < m; ++row)
{
for (int col = 0; col < n; ++col)
{
*(mat_ptr + ((row * n) + col)) = (row * n) + col;
}
}
for (int row = 0; row < m; ++row)
{
for (int col = 0; col < n; ++col)
{
std::cout << *(mat_ptr + ((row * n) + col)) << " ";
}
std::cout << std::endl;
}
}
return 0;
}
我个人更喜欢使用 wohlstad 的方法,但您也可以 variably-modified 类型,这是 C11 的可选功能,but will probably be mandated in C2x:
int (*p)[m] = malloc(n * sizeof *p);
这现在可以像普通二维数组一样使用,具有自动存储持续时间。
int n = 12, m = 9;
int (*p)[m] = malloc(n * sizeof *p);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
p[i][j] = i * m + j;
printf("%d\n", p[4][2]);
free(p);