对于2D数组,所有行的一个malloc调用如何工作?
我知道我们可以使用指针实现动态多维数组,有很多方法可以实现,单指针和双指针都可以。但是,在探索这个主题时,我发现了这段代码,我无法理解其中的头尾部分。有人能解释一下下面的代码是如何工作的吗 也请解释一下, 1) 当我们将内存分配给对于2D数组,所有行的一个malloc调用如何工作?,c,pointers,multidimensional-array,dynamic-memory-allocation,C,Pointers,Multidimensional Array,Dynamic Memory Allocation,我知道我们可以使用指针实现动态多维数组,有很多方法可以实现,单指针和双指针都可以。但是,在探索这个主题时,我发现了这段代码,我无法理解其中的头尾部分。有人能解释一下下面的代码是如何工作的吗 也请解释一下, 1) 当我们将内存分配给arr[i]作为r*c*sizeof(int)时,为什么有必要将r*sizeof(int*)分配给arr[i]呢。 2) 为什么需要执行arr[i]=*arr+c*i 由于我对这种动态内存分配非常陌生,并且非常渴望深入挖掘,因此产生了这些问题。对不起,如果它是基本的,但
arr[i]
作为r*c*sizeof(int)
时,为什么有必要将r*sizeof(int*)
分配给arr[i]
呢。
2) 为什么需要执行arr[i]=*arr+c*i
由于我对这种动态内存分配非常陌生,并且非常渴望深入挖掘,因此产生了这些问题。对不起,如果它是基本的,但我仍然不知道它。
谢谢
不是为
arr
中分配的每个r
指针分配,而是仅使用第一个指针为rxc
数组分配内存。其余的指针指向这个内存块
好处是可以使用singlememset
初始化数组。释放要容易得多(只需释放第一个指针分配的内存)
arr[i]=(*arr+c*i)
这基本上是初始化指针arr[i]
,指针应该指向的相关部分
从分配的内存开始,它将在哪里?
有arr[0]
,arr[1]
。arr[i-1]
指针指向各自包含c
元素的行。因此c
指针的每个i
元素-i*c
元素都已经被解决了。因此,arr[i]
指向的下一个将是(*arr+c*i)
在编辑问题之后:
OP问我们为什么需要做arr=(int**)malloc(sizeof(int*)*r)
我想这张图片解释的远不止文字
arr --> [0] [1] [2] [3] .....[r-2] [r-1]
| | | | | |
V | | | | |
[0] <-+ | | | |
[1] | | | |
[2] | | | |
[3] | | | |
[4] | | | |
. | | | |
| | | |
[c-1] | | | |
[c] <----+ | | |
[c+1] | | |
[c+2] | | |
. | | |
. | | |
. | | |
[2c] <----------+ | |
[2c+1] | |
[2c+2] | |
. | |
. | |
. | |
[(r-2)*c] <------------------+ |
[(r-2)*c+1] |
. |
. |
[(r-2)*c+(c-1)] |
[(r-1)*c] <----------------------+
[(r-1)*c+1]
[(r-1)*c+2]
[(r-1)*c+3]
[(r-1)*c+(c-1)]~[rc-1]
arr-->[0][1][2][3]
| | | | | |
V | | | ||
[0]不是为arr
中分配的每个r
指针分配内存,而是只使用第一个指针为rxc
数组分配内存。其余的指针指向这个内存块
好处是可以使用singlememset
初始化数组。释放要容易得多(只需释放第一个指针分配的内存)
arr[i]=(*arr+c*i)
这基本上是初始化指针arr[i]
,指针应该指向的相关部分
从分配的内存开始,它将在哪里?
有arr[0]
,arr[1]
。arr[i-1]
指针指向各自包含c
元素的行。因此c
指针的每个i
元素-i*c
元素都已经被解决了。因此,arr[i]
指向的下一个将是(*arr+c*i)
在编辑问题之后:
OP问我们为什么需要做arr=(int**)malloc(sizeof(int*)*r)
我想这张图片解释的远不止文字
arr --> [0] [1] [2] [3] .....[r-2] [r-1]
| | | | | |
V | | | | |
[0] <-+ | | | |
[1] | | | |
[2] | | | |
[3] | | | |
[4] | | | |
. | | | |
| | | |
[c-1] | | | |
[c] <----+ | | |
[c+1] | | |
[c+2] | | |
. | | |
. | | |
. | | |
[2c] <----------+ | |
[2c+1] | |
[2c+2] | |
. | |
. | |
. | |
[(r-2)*c] <------------------+ |
[(r-2)*c+1] |
. |
. |
[(r-2)*c+(c-1)] |
[(r-1)*c] <----------------------+
[(r-1)*c+1]
[(r-1)*c+2]
[(r-1)*c+3]
[(r-1)*c+(c-1)]~[rc-1]
arr-->[0][1][2][3]
| | | | | |
V | | | ||
[0]在C语言中,数组以“行主”顺序存储在内存中。这意味着在二维数组中,同一行中的元素与内存中的另一行相邻,因此同一列中的元素按列数(即行宽)隔开
*arr
返回指向int的指针,因为它正在解引用指向int的指针。具体而言,它是由名称arr指向的指针。这是数组的基址
arr[i]也是指向int的指针。现在请记住我说过的关于row-major的内容。第i行指针应指向何处?答案是,在数组的底部(*arr
)加上i
乘以列数(c
)。让你困惑的循环仅仅是让其他循环指向正确的位置,这样当需要使用arr[r][c]
表示法时,隐含的指针算法就可以工作了
瞧。在C语言中,数组是按“行主”顺序存储在内存中的。这意味着在二维数组中,同一行中的元素与内存中的另一行相邻,因此同一列中的元素按列数(即行宽)隔开
*arr
返回指向int的指针,因为它正在解引用指向int的指针。具体而言,它是由名称arr指向的指针。这是数组的基址
arr[i]也是指向int的指针。现在请记住我说过的关于row-major的内容。第i行指针应指向何处?答案是,在数组的底部(*arr
)加上i
乘以列数(c
)。让你困惑的循环仅仅是让其他循环指向正确的位置,这样当需要使用arr[r][c]
表示法时,隐含的指针算法就可以工作了
瞧。这段代码分配了两个内存区域
arr
能够包含指向int的r
指针
arr[0]
区域,用于r*c
int
(*arr+c*i)
与&arr[0][c*i]
然后为每个r
(行)分配一个指针,指向arr[0]
中的一个位置,其间隔为c
(列)int(用于存储c
int)
然后它只将数组视为一个arr[row][col]
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count;
(i=0;i
对于(j=0;jfor(i = 0; i < r; i++)
arr[i] = (*arr + c * i);
arr: 0:P 1:P 2:P
| | |
v v v
arr[0]: IIIIIIIIIIII
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count;