C 为什么不';我们必须将多维数组的行大小传递给函数吗?
函数C 为什么不';我们必须将多维数组的行大小传递给函数吗?,c,arrays,C,Arrays,函数void transpossematrix(int a[][arraySize])中的第一个索引为空的原因是什么 当您拥有foo类型的n对象数组a时,编译器可以通过将i乘以foo对象的大小添加到a的起始地址来计算元素a[i]的位置 请注意,此计算仅涉及foo的大小和下标i。它不涉及元素的数量n。编译器不需要知道元素的数量就可以计算元素的位置 您需要知道数组中的元素数,以避免超出数组的末尾。然而,在C语言中,防止超出数组末尾并不是编译器的工作。函数的作者负责这样做。因此,为此,编译器不需要知道
void transpossematrix(int a[][arraySize])
中的第一个索引为空的原因是什么 当您拥有foo
类型的n
对象数组a
时,编译器可以通过将i
乘以foo
对象的大小添加到a
的起始地址来计算元素a[i]
的位置
请注意,此计算仅涉及foo
的大小和下标i
。它不涉及元素的数量n
。编译器不需要知道元素的数量就可以计算元素的位置
您需要知道数组中的元素数,以避免超出数组的末尾。然而,在C语言中,防止超出数组末尾并不是编译器的工作。函数的作者负责这样做。因此,为此,编译器不需要知道数组中有多少个元素
现在假设每个foo
对象本身就是m
类型的bar
对象数组。编译器确实需要知道foo
对象的大小。一个foo
有多大?由于foo
是bar
类型的m
对象数组,其大小是m
乘以bar
的大小。因此,要知道foo
有多大,编译器需要知道数组中有多少个元素
因此,当向[FirstDimension][SecondDimension]传递
int时,编译器不需要知道FirstDimension
,而是需要知道SecondDimension
,,因为TransposeSematrix
接收的实际上不是2D数组,而是指向1D数组的指针
除非它是sizeof
或一元&
运算符的操作数,或者是用于初始化声明中字符数组的字符串文字,否则“T
的N元素数组”类型的表达式将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址
如果将数组声明为
int arr[N][M];
并将其传递给函数
void foo( arr );
然后表达式arr
从类型“int的M元素数组的N元素数组”转换为“int的M元素数组的指针”(int(*)[M]
)
在函数参数声明中,ta[N]
和ta[]
被“调整”为ta*a
-IOW,这三个函数都将a
声明为指向T
的指针(这仅适用于函数参数声明)
因此,
void transposeMatrix(int a[][arraySize])
相当于
void transposeMatrix(int (*a)[arraySize])
使用a[][M]
而不是(*a)[M]
是一种符号方便(类似于使用p->M
而不是(*p).M
通过指针访问struct
和union
成员)
由于数组索引的工作方式,您可以像任何其他二维数组一样索引到a
。请记住,下标操作a[i]
定义为*(a+i)
-给定起始地址a
,找到a
后面的i
第个元素(不是字节)的地址,然后取消引用结果。因此:
(*a)[i] == (*(a + 0))[i] == (a[0])[i] == a[0][i]
意义
(*(a + j))[i] == (a[j])[i] == a[j][i]
因为数组会衰减为指针。因为函数只需要第二个维度就可以正确计算
a[i][j]
的位置。据推测,函数还有其他方法来确定行数。另请参见。请注意,第一个维度不是“行大小”;它是行数。行大小是二维数组的第二个维度,必须提供。如果你处理的是3D或更高维的数组,那么除了第一个以外的所有大小都必须以这样或那样的方式提供(“另一个”使用VLA表示法)。数组到指针的自动转换是如何相关的?假设数组没有自动转换为指针。然后,当一个数组a
被传递给一个函数时,它必须通过一些其他机制来传递,例如通过引用或复制,尽管其他方法也是可能的。例如,如果它是一个非常小的数组,例如n的char[n][2]
≤4,它可以完全在8字节寄存器中传递,就像一些ABI对小结构所做的那样。被调用的例程不需要知道n。因此,并不是转换为指针才可以省略第一个维度。