int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
*matrix = malloc(20 * sizeof(int));
我只是不了解双指针的概念以及它如何转换为二维数组(即为true)。 预先感谢。
答案 0 :(得分:6)
从技术上讲,这里创建的不是二维数组,而是一个指针数组,每个指针都包含一个数组的起始地址。然后可以将其索引为好像是“真实的” 2D数组。
此行创建一个由5个指向int
的指针组成的数组:
matrix = malloc(5 * sizeof(int*));
下一行创建单个数组20 int
:
*matrix = malloc(20 * sizeof(int));
但是就2D数组而言,这是不完整的,因为仅分配了一行。您需要遍历matrix
指向的每个元素才能创建每一行:
int **matrix, i;
matrix = malloc(5 * sizeof(int*));
for (i=0; i<5; i++) {
matrix[i] = malloc(20 * sizeof(int));
}
使用完此动态2D数组后,您需要以相反的顺序释放内存:
for (i=0; i<5; i++) {
free(matrix[i]);
}
free(matrix);
这与真实的2D阵列在某些方面有所不同。首先,在真正的2D数组中,所有元素在内存中都是连续的,在这种情况下,指针数组和每个行数组都不是。
另一个区别是,当传递给函数时,不能像传递真实2D数组那样传递它。
对于简单的一维数组,无论是在编译时分配还是动态分配:
int a1[5];
int *a2 = malloc(5 * sizeof(int));
两者都可以传递给这样的函数:
void f(int *a);
但是对于2D数组:
int a[5][20];
它需要传递给这样的函数:
void f(int a[5][20]);
或等效地:
void f(int (*a)[20]);
动态2D数组需要传递给这样的函数:
void f(int **a);
答案 1 :(得分:6)
某些图片可能会有所帮助。
让我们从y
开始,它是指向matrix
的指针:
int
在第一次致电 int **
+--------+
| matrix |---???
+--------+
之后,您将拥有以下内容:
malloc
您已为5个 int ** int *
+--------+ +-----------+
| matrix |--->| matrix[0] |
+--------+ +-----------+
| matrix[1] |
+-----------+
| matrix[2] |
+-----------+
| matrix[3] |
+-----------+
| matrix[4] |
+-----------+
对象动态分配了空间,并且int *
指向第一个对象。在第二次致电matrix
之后,您将拥有以下内容(表达式malloc
等效于*matrix
-以下更多内容):
matrix[0]
您已为20个 int ** int * int
+--------+ +-----------+ +---------------+
| matrix |--->| matrix[0] |--->| matrix[0][0] |
+--------+ +-----------+ +---------------+
| matrix[1] | | matrix[0][1] |
+-----------+ +---------------+
| matrix[2] | | matrix[0][2] |
+-----------+ +---------------+
| matrix[3] | ...
+-----------+ +---------------+
| matrix[4] | | matrix[0][19] |
+-----------+ +---------------+
对象动态分配了空间,并且int
指向第一个对象。
因此,简而言之-每个matrix[0]
是一个matrix[i][j]
。每个int
都指向matrix[i]
,因此每个matrix[i][0]
必须是指向matrix[i]
或int
的指针。 int *
指向matrix
,这意味着matrix[0]
必须是指向matrix
或int *
的指针。
请记住,数组下标表达式int **
被定义为a[i]
-给定地址*(a + i)
,偏移量a
elements < / em>(不是字节!),然后引用结果。因此,i
等效于*matrix
,等效于*(matrix + 0)
。
现在,这里的不是真正的2D数组-您有一个指针序列,每个指针都可以指向matrix[0]
对象序列的第一个(或一无所有)。阵列的“行”在内存中将很可能不相邻。在真正的2D数组中,所有数组元素都是连续的。给定
int
元素将如下所示:
int matrix[5][20];
编辑
指针到指针和2D数组之间的其他一些关键区别。首先,假设以下定义:
+---------------+
| matrix[0][0] |
+---------------+
| matrix[0][1] |
+---------------+
...
+---------------+
| matrix[0][19] |
+---------------+
| matrix[1][0] |
+---------------+
| matrix[1][1] |
+---------------+
...
+---------------+
| matrix[4][19] |
+---------------+
表达式int **ptr;
int matrix[ROWS][COLS];
的类型为ptr
。表达式int **
将从类型matrix
“衰减”到类型int [ROWS][COLS]
(指向int (*)[COLS]
的元素,指向COLS
的元素数组);
int
给出指针本身的大小(4、8或其他一些字节数)。 sizeof ptr
以字节为单位(sizeof matrix
)给出整个数组的大小。
表达式ROW * COLS * sizeof (int)
,&matrix
,matrix
和&matrix[0]
都将产生相同的 value (数组的第一个元素),尽管表达式的类型将不同-分别为&matrix[0][0]
,int (*)[ROWS][COLS]
,int (*)[COLS]
和int (*)[COLS]
。表达式int *
,&ptr
,ptr
和&ptr[0]
不会产生相同的值-&ptr[0][0]
和&ptr
的值将不同于&ptr[0][0]
和ptr
,表达式的类型将为&ptr[0]
,int ***
,int **
和int **
。
答案 2 :(得分:2)
我认为您需要以下条件:
int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
for (int i=0; i<5; i++)
matrix[i] = malloc(20 * sizeof(int));
在这里,您首先为行分配一个指针数组。然后为每一行分配内存。