对于2D数组,所有行的一个malloc调用如何工作?

对于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 由于我对这种动态内存分配非常陌生,并且非常渴望深入挖掘,因此产生了这些问题。对不起,如果它是基本的,但

我知道我们可以使用指针实现动态多维数组,有很多方法可以实现,单指针和双指针都可以。但是,在探索这个主题时,我发现了这段代码,我无法理解其中的头尾部分。有人能解释一下下面的代码是如何工作的吗

也请解释一下,

1) 当我们将内存分配给
arr[i]
作为
r*c*sizeof(int)
时,为什么有必要将
r*sizeof(int*)
分配给
arr[i]
呢。 2) 为什么需要执行
arr[i]=*arr+c*i

由于我对这种动态内存分配非常陌生,并且非常渴望深入挖掘,因此产生了这些问题。对不起,如果它是基本的,但我仍然不知道它。 谢谢


不是为
arr
中分配的每个
r
指针分配,而是仅使用第一个指针为
rxc
数组分配内存。其余的指针指向这个内存块

好处是可以使用single
memset
初始化数组。释放要容易得多(只需释放第一个指针分配的内存)

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
数组分配内存。其余的指针指向这个内存块

好处是可以使用single
memset
初始化数组。释放要容易得多(只需释放第一个指针分配的内存)

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;