c语言 - multiArray 和 multiArray[0] 和 &multiArray[0] 相同?



在第6行,而不是multiArray[0],当我写multiArray时,程序仍然可以工作。不明白为什么。我之前认为multiArray是指向multiArray[0]的指针,它是指向multiArray[0][0]的指针。因此,multiArray本身就是一个指向指针的指针。multiArray[0]是一个指向4元素int数组的指针。看来multiArray和multiArray[0]肯定不一样。但在下面的代码中,两者都有效。我编写的Print函数需要一个指向4元素int数组的指针。因此,只有multiArray[0]必须工作,而multiArray不能工作。但两者都有效。我不明白。

#include <stdio.h>
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]的句法糖。您可以去掉像4 + 5这样的表达式,并通过操作4字节的数组来获得相同的结果。

如果你想进一步理解这个概念,你甚至可以说C只是通用图灵机脚本的语法糖。

事实上,多维数组是C中类型系统的一部分,它们有与之相关的语法。剥猫皮的方法不止一种。

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

因此,int multiArray[3][4]是一个由3个元素组成的数组。这些元素中的每一个都是4个CCD_ 5的阵列。

在内存中,一个数组的元素是连续存储的,而不管元素类型是什么。因此,内存布局是一个4个int的数组,紧接着是另一个4 int的数组,最后是另一组4 int的数组。

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

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

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

有些演示只关注其中的第一个,他们会说"指针只是一个数字"之类的话。但这就是忘记了类型信息,而类型信息是指针的关键部分。

使用%p打印指针时,会丢失类型信息。你只是把第一个字节在内存中的位置放出来。因此,它们看起来都是一样的,尽管三个指针指向不同大小的物体(它们像马特鲁斯卡娃娃一样相互重叠)。

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

脚注:所有这些都独立于C的一些语法怪癖;这些年来引起了很多混乱(但有时也很有用)。如果x是数组,则表达式x&x[0]的快捷方式,但用作&sizeof的操作数时除外。(否则,这将是一个递归定义!)。第二个怪癖是,如果你在函数形式参数列表中写一个看起来像数组声明符的东西,实际上就像你写了一个指针声明符。我再次强调,这些只是语法上的奇怪之处,它们并没有说明数组和指针的本质,实际上并没有那么复杂。如果没有这两种怪癖,这种语言也同样有效。

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

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

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

试试这个:

void t1(int* param)
{
  printf("t1: %dn", *param);
}
void t2(int** param)
{
  printf("t2: %dn", **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*,而point的类型是int [4]*(指向4整数数组的指针)。

相关内容

  • 没有找到相关文章