[] 运算符处理指针的方式与处理数组表达式的方式几乎相同,因此无论您如何分配,您都可以使用 Pond[i][j] 访问特定元素(除非您将其分配为一维数组dom0 显示)。
如果在编译时知道行数和列数,这是最简单的:
#define M ... // rows
#define N ... // columns
int (*Pond)[N] = malloc ( sizeof *Pond * M);
...
Pond[i][j] = x;
...
free( Pond );
变量Pond的类型是“指向N的指针-int的元素数组”。 表达式 *Pond 的类型是“int 的 N 元素数组”。所以sizeof *Pond 给了我们N-element 数组int 中的字节数;我们将其乘以M 以获得数组所需的总字节数。
由于a[i] 被评估为*(a + i),[] 运算符在指针表达式上的工作方式与在数组表达式上的工作方式相同1;也就是说,您可以在这里使用Pond[i][j],就像使用常规二维数组一样。
如果在运行时才知道行数和列数,但是您使用的是支持可变长度数组的 C99 编译器或 C2011 编译器,则几乎相同: p>
size_t n, m;
/**
* get values of n and m
*/
int (*Pond)[n] = malloc( sizeof *Pond * m );
...
Pond[i][j] = x;
...
free( Pond );
与上述相同,只是 m 和 n 直到运行时才知道。在这两种情况下,动态分配的数组都是连续的(所有行在内存中都是相邻的)。
+---+
Pond: | | ---+
+---+ |
... |
+---+ |
Pond[0][0]: | | <--+
+---+
Pond[0][1]: | |
+---+
...
+---+
Pond[0][n-1]: | |
+---+
Pond[1][0]: | |
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[m-1][0]: | |
+---+
Pond[m-1][1]: | |
+---+
...
+---+
Pond[m-1][n-1]: | |
+---+
如果直到运行时才知道行数和列数,并且您使用的编译器不支持 VLA,则您有两种选择,具体取决于您是否希望数组是连续的。
如果数组不必连续,可以使用两步分配方法:
size_t n, m;
/**
* get values for n and m
*/
int **Pond = malloc( sizeof *Pond * m ); // allocate m rows of pointer to int
if ( Pond )
{
for ( size_t i = 0; i < m; i++ )
{
Pond[i] = malloc( sizeof *Pond[i] * n ); // allocate n columns of int for each row
}
}
在这种情况下,Pond 是指向int 的指针;它将最终指向一个有效的一维指针数组,指向int;这些指针中的每一个都将指向int 的一维数组,类似于以下内容:
+---+
Pond: | | ---+
+---+ |
|
+------+
|
V
+---+
Pond[0]: | | ------------+
+---+ |
Pond[1]: | | ---------+ |
+---+ | |
Pond[2]: | | | |
+---+ | |
... | |
+---+ | |
Pond[m-1]: | | | |
+---+ | |
| |
+---+ | |
Pond[0][0]: | | <--------|--+
+---+ |
Pond[0][1]: | | |
+---+ |
... |
+---+ |
Pond[0][n-1]: | | |
+---+ |
|
+---+ |
Pond[1][0]: | | <--------+
+---+
Pond[1][1]: | |
+---+
...
+---+
Pond[1][n-1]: | |
+---+
但是因为Pond[i][j] 被评估为*(*(Pond + i) + j),所以它仍然有效。
请注意,由于这是一个两步分配过程,释放也需要两个步骤:
for ( size_t i = 0; i < m; i++ )
free( Pond[i] );
free( Pond );
如果数组确实需要连续,那么您必须将内存分配为一维数组并手动计算索引:
int *Pond = malloc( sizeof *Pond * m * n );
...
Pond[ i * m + j ] = x;
...
free( Pond );
1。在大多数情况下,数组表达式将被转换或“衰减”为指针表达式,因此下标实际上是对指针表达式起作用。