在C中,当使用malloc创建2D数组时,为什么在传递到函数时不需要指定2D数组大小?

在C中,当使用malloc创建2D数组时,为什么在传递到函数时不需要指定2D数组大小?,c,multidimensional-array,parameter-passing,heap-memory,stack-memory,C,Multidimensional Array,Parameter Passing,Heap Memory,Stack Memory,我对C相当陌生,只是对将HEAP内存中分配的2D数组传递到函数时实际发生的情况感到困惑。我已经写了三个函数的代码,A,B,C来演示我的问题 基本上,当我在函数-a的堆栈空间中创建2d数组时,我能够将2d数组指针传递给函数-B,该函数需要参数(int size,int(*arr)[size]),并且工作正常。我的理解是“int size”变量需要让arr指针现在指示每个增量应该跳转多少空间 但是,当我在函数-a的堆空间中创建2d数组时,将其传递给函数-B似乎会丢失数据的位置(请参见代码)。但是,如

我对
C
相当陌生,只是对将
HEAP
内存中分配的2D数组传递到函数时实际发生的情况感到困惑。我已经写了三个函数的代码,A,B,C来演示我的问题

基本上,当我在函数-a的堆栈空间中创建2d数组时,我能够将2d数组指针传递给函数-B,该函数需要参数
(int size,int(*arr)[size])
,并且工作正常。我的理解是“int size”变量需要让arr指针现在指示每个增量应该跳转多少空间

但是,当我在函数-a的堆空间中创建2d数组时,将其传递给函数-B似乎会丢失数据的位置(请参见代码)。但是,如果我将这个堆空间2d数组传递给具有参数
(int**arr)
的function-C,它就可以正常工作

如果有人能解释为什么在将堆空间2d数组传递给function-C时不需要指定大小,那就太好了。另外,当我将在
STACK
space中创建的2d数组传递给function-C时,它崩溃了,这是为什么

下面是显示我的问题()的示例代码:

#包括
#包括
无效函数_A(int num)
{
//为2D数组分配堆空间
int**arrHEAP=(int**)malloc(2*sizeof(int*);
arrHEAP[0]=(int*)malloc(5*sizeof(int));
arrHEAP[1]=(int*)malloc(5*sizeof(int));

对于(int i=0;i数组/指针转换

理解的缺陷在于数组的使用和指针的使用。在C语言中,数组是一种不同类型的对象。导致混淆的原因之一是数组在访问时被转换为指向其第一个元素的指针。(数组/指针转换)这由(注意不发生数组/指针转换的4个例外情况)

这里的键是type

int arrSTACK[2][5] = {{100, 200, 300, 400, 500},{600,700,800,900,1000}};
在访问时,它将被转换为指针——但类型是什么?C中的2D数组是由1D数组组成的数组。数组/指针转换仅适用于第一级间接寻址。因此,在访问时,
arrSTACK
被转换为指向数组的指针
int[5]
。因此它的类型是
int(*)[5]
。由于类型控制指针算术
arrSTACK+1
前进五个整数值,因此它指向构成
arrSTACK
(第二行)的第二个1D数组的开头

指针

int**arrHEAP
声明一个指针。指向
int
的指针。它与数组无关。但是,指向指针的指针可以被索引,就像索引2D数组以寻址存储在内存中的单个整数一样。这是2D数组和通过分配存储指针,然后为整数分配存储,并将每个保存整数的块的起始地址分配给已分配的指针之一。这里不能保证
arrHEAP
的所有元素在内存中都是连续的,就像它们与2D数组一样

因此,让我们看看指针算法如何与
arrHEAP
一起工作的区别。当您取消引用
arrHEAP
时,指向指针的指针(例如
arrHEAP[0]
)取消引用会产生什么类型的结果?如果您有一个指向
int
的指针,并且您取消引用了它,那么只剩下指向
int
的指针。因此,对于数组,取消引用会产生指向
int[5]
的类型指针,而对于
arrHEAP[0]
来说,结果只是指向
int
的指针(没有
5
——它只是一个指向
int
)的指针。那么指针算法有什么不同呢?
arrSTACK+1
将指针向前推进
5*sizeof(int)
字节(
20
-bytes)。使用
arrHEAP+1
只前进到分配的指针块中的下一个指针(1-pointer
8
-bytes)

这就是为什么不能将一个传递给另一个函数的原因。期望数组的函数理解
arrSTACK[0]
arrSTACK[1]
相隔
20
-字节,而指针
arrHEAP[0]
arrHEAP[1]
仅相隔8个字节。这是您生成的指针不兼容警告和错误的症结所在

然后,缺乏保证
arrSTACK
的所有值在内存中都是顺序的
总是从数组开头算起20个“是”。使用
arrHEAP
时,从邻接的角度来看,第一个分配的指针与另一个指针没有保证的关系。以后可以替换或重新分配它们

这意味着如果您尝试向
函数C(int**arr)
提供
arrSTACK
,编译器将为不兼容的指针类型生成警告,因为它们是。相反,如果您尝试向
函数B(int size,int(*arr)[size]提供
arrHEAP
由于指针类型不兼容,它同样会再次发出警告——因为它们是不兼容的

即使对象和数组在另一个函数中的使用方式看起来像是可行的,因为基本上是以相同的方式对两者进行索引,编译器也不能让一个不兼容的类型通过——这不是编译器的工作

编译器的操作只能基于您在编写代码时对它所做的承诺。对于
function_B(int size,int(*arr)[size])
您承诺要发送一个包含
5 int
的1D数组的2D数组,其中
function_C(int**arr)
,您向编译器承诺您将提供指向
int
的指针。当编译器发现您试图将错误对象作为参数传递时,它将发出警告,
int arrSTACK[2][5] = {{100, 200, 300, 400, 500},{600,700,800,900,1000}};