multiArray和multiArray 和&multiArray 相同?

在第6行而不是multiArray [0],当我编写multiArray时,程序仍然有效。 不明白为什么。 我之前想过,multiArray是指向multiArray [0]的指针,它是指向multiArray [0] [0]的指针。 所以multiArray就是一个指向指针的指针。 multiArray [0]是指向4元素int数组的指针。 所以似乎multiArray和multiArray [0]必须是不同的。 但是在下面的代码中,两者都有效。 我写的打印函数需要一个指向4元素int数组的指针。 所以只有multiArray [0]必须工作,而multiArray必须不能工作。 但两者都有效。 不明白。

#include  void printArr(int(*ptr)[4]); int i, k; int main(void){ int multiArray[3][4] = { { 1, 5, 2, 4 }, { 0, 6, 3, 14 }, { 132, 4, 22, 5 } }; int(*point)[4] = multiArray[0]; for (k = 0; k < 3; k++) { printArr(point++); } getchar(); } void printArr(int(*ptr)[4]){ int *temp = (int *)ptr; for (i = 0; i < 4; i++) { printf("%d ", *temp); temp++; } puts("\n"); } 

其他人写道“多维数组是1-D数组的语法糖”。

这有点像说int只是unsigned char[4]语法糖unsigned char[4] 。 您可以取消像4 + 5这样的表达式,并通过操作4个字节的数组来获得相同的结果。

如果你想进一步采用这个概念,你甚至可以说C只是Universal Turing Machine脚本的语法糖。

实际情况是,多维数组是C中类型系统的一部分,并且它们具有与之相关的语法。 皮肤猫的方法不止一种。

继续前进,C安排我们称之为多维数组的方式是:“数组只能有一个维度,但元素类型本身可能是另一个数组”。 我们说“多维数组”是为了方便,但语法和类型系统实际上反映了数组的一维性质。

因此, int multiArray[3][4]是一个包含3个元素的数组。 每个元素都是4个ints的数组。

在内存中,数组的元素是连续存储的 – 无论元素类型是什么。 所以,内存布局是一个4 int的数组,紧接着是另一个4 int数组,最后是另一个4 int数组。

内存中有12个连续的int ,在C类型系统中,它们被分成3组,每组4个。

你会注意到12的第一个int也是第一个4的第一个int 。这就是为什么我们发现如果我们问“第一个int的内存位置是什么?”,“什么是内存位置第一组4个整数?“和”整个12个整体的内存位置是什么?“,我们每次都得到相同的答案。 (在C中,多字节对象的内存位置被认为是从其第一个字节的位置开始)。

现在,来谈谈指针语法和表示。 在C中,指针告诉您在内存中可以找到对象的位置。 这有两个方面:对象的内存位置,以及它的对象类型。 (对象的大小是类型的推论)。

有些演讲只关注第一部分,他们会说“指针只是一个数字”。 但这是忘记类型信息,这是指针的关键部分。

使用%p打印指针时,会丢失类型信息。 你只是在第一个字节的内存中放置位置。 所以它们看起来都一样,尽管事实上三个指针指向不同大小的物体(它们像matruskha娃娃一样彼此重叠)。

在C的大多数实现中,类型信息都是在编译时计算的,所以如果你试图通过比较源代码和汇编代码来理解C(有些人这样做),你只能看到指针的内存位置部分。 如果您忘记类型信息也很重要,这可能会导致误解。

脚注:所有这些都与C所具有的几个语法怪癖无关; 这些年来引起了很多混乱(但有时也很有用)。 如果x是数组,则表达式x&x[0]的快捷方式,除非用作&sizeof的操作数。 (否则这将是一个递归定义!)。 第二个怪癖是如果你在函数forms参数列表中编写类似于数组声明符的内容,实际上就好像你编写了一个指针声明符。 我再次强调这些只是语法怪异,他们并没有说任何关于数组和指针的本质的基本原理,实际上并没有那么复杂。 如果没有这两种怪癖,这种语言也会起作用。

多维数组var_t arr[size_y][size_x]提供了以方便的方式声明和访问数组元素(内存)的方法。 但是所有多维数组都是内部连续的内存块。

你可以说arr[y][x] = arr[y*cols+x]

就指针级而言,指针multiArraymultiArray[0]是相同的,它们是int* – 尽管arr的forms类型int (*)[2] 。 使用该类型将允许人们利用所有指针机制(这种指针上的++将地址移动8个字节,而不是4个)。

试试这个:

 void t1(int* param) { printf("t1: %d\n", *param); } void t2(int** param) { printf("t2: %d\n", **param); } int main(void) { int arr[2][2] = { { 1, 2 } , { 3, 4 } }; t1(arr); // works ok t1(arr[0]); // works ok t2(arr); // seg fault t2(arr[0]); } 

int(*point)[4] = multiArray[0];

这是因为multiArray[0]multiArray指向相同的地址,即数组的第一个元素的地址: multiArray[0][0]

但是在这种情况下,您可能会收到编译器的警告,因为multiArray[0]类型是int*pointint [4]* (指向4整数数组的指针)。