为什么我们不能使用双指针来表示二维数组?

为什么我们不能使用双指针来表示二维数组?

arr[2][5] = {"hello","hai"}; **ptr = arr; 

为什么双指针(** ptr)在这个示例中不起作用?

我打算画出怎样的方法

 int array[10][6]; 

 int **array2 = malloc(10 * sizeof *array2); for (int i = 0; i < 10; ++i) array2[i] = malloc(6 * sizeof **array2); 

看起来像在记忆中以及它们是如何不同的(并且它们不能相互铸造)

array看起来像:

  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | | | | | | | | | | | ..............| | | (10*6 elements of type int) - - - - - - - - - - - - - - - - - - - - - - < first row >< second row> ... 

array2看起来像:

  _ _ _ _ _ _ _ _ _ _ | | | | | | | | | | | (10 elements of type int *) - - - - - - - - - - | | .... | _ _ _ _ _ _ | | \-->| | | | | | | (6 elements of type int) | | - - - - - - | | | | _ _ _ _ _ _ | \ -->| | | | | | | (6 elements of type int) | - - - - - - | | | _ _ _ _ _ _ \ -->| | | | | | | (6 elements of type int) - - - - - - 

当你说array[x][y] ,它转换为*((int *)array+x*6+y)

虽然,当你说array2[x][y] ,它转换为*(*(array2+x)+y) (注意,对于array ,这个公式也有效(读到post的末尾,然后是注释) ))。

也就是说,静态2d数组实际上是1d数组,其中行放在一行中。 索引由公式row * number_of_columns_in_one_row + column

然而,动态2d数组只是一个指针数组。 然后,每个指针被动态分配以指向另一个1d数组。 事实上,指针可以是任何东西。 可以为NULL ,或指向单个变量,或指向另一个数组。 并且每个指针都是单独设置的,因此它们可以具有不同的性质。

如果你需要在某处传递array的指针,你就不能把它转换为int ** (想象一下会发生什么。 array的单元格的int值被解释为指针和解引用 - > Bam!Segmentation fault!)。 然而,您可以将array视为int [6]的1d数组; 这是一个元素的1d数组,类型为int [6] 。 要写下来,你说

 int (*p)[6] = array; 

指向指针指示每行(或列,如果您更喜欢这样想)可以具有与其他行/列不同的长度。

您还可以通过指向start元素的指针来表示2D数组,并使用一个整数来指定每行/每列的元素数:

 void matrix_set(double *first, size_t row_size, size_t x, size_t y, double value) { first[y * row_size + x] = value; } 

在C中,二维数组是数组的数组

你需要一个指向数组的指针来引用它,而不是一个双指针:

 char array[2][6] = {"hello", "hai"}; char (*p)[6] = array; //char **x = array; // doesn't compile. 

对于指向“2维数据”的双指针,它必须引用指针数组的第一个元素。 但是C(数组数组)中的二维数组与指针数组不同,如果只定义一个二维数组,则不存在相应的指针数组。

两者之间唯一的相似之处是用于访问数据的[][]语法:数据本身的结构完全不同。

为了获得一个“看起来像”一个可变大小的多维数组的对象,为每个行创建一个指针数组是一个昂贵的设计选择,为了语法糖 。 不要这样做。

执行可变大小多维数组的正确方法如下:

 if (w > SIZE_MAX/sizeof *m/h) goto error; m = malloc(w * h * sizeof *m); if (!m) goto error; ... m[y*w+x] = foo; 

如果你想让它“看起来很漂亮”,那么你可以写m[y][x] ,你应该使用不同的语言,也许是C ++。

让我们从谈论法律代码开始吧。 您编写的内容(假设每个声明前面有一个char)将无法编译,原因如下:您有太多的初始值设定项(arr [0]为6个字符,其大小为5),当然还有char ** p没有与char arr兼容的类型[2] [5]。 纠正这些问题,我们得到:

 char arr[2][6] = { "hello", "hai" }; char (*p)[6] = arr; 

没有任何双指针。 如果要访问上面的单个字符,则需要指定它们来自的元素:

 char* pc = *arr; 

如果你想从arr中的第一个元素访问字符,它会工作。

C ++没有二维数组。 上面的第一个定义定义了char的数组[2]或数组[6]。 指针转换的implicite数组导致指向char的数组[6]的指针。 在那之后,当然,没有数组到指针转换,因为你不再有一个数组。