为什么我们不能使用双指针来表示二维数组?
为什么我们不能使用双指针来表示二维数组?
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]的指针。 在那之后,当然,没有数组到指针转换,因为你不再有一个数组。