multiArray和multiArray [0]和& multiArray [0]相同?

时间:2014-04-10 09:16:47

标签: c multidimensional-array

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

3 个答案:

答案 0 :(得分:3)

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

这有点像说int只是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[0]x的快捷方式,除非用作&sizeof的操作数。 (否则这将是一个递归定义!)。第二个怪癖是,如果你在函数形式参数列表中编写类似于数组声明符的内容,实际上就好像你编写了一个指针声明符。我再次强调这些只是语法怪异,他们并没有说任何关于数组和指针的本质的基本原理,实际上并没有那么复杂。如果没有这两种怪癖,这种语言也会起作用。

答案 1 :(得分:1)

多维数组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: %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]);
}

答案 2 :(得分:0)

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

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

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