为了账号安全,请及时绑定邮箱和手机立即绑定

创建指向二维数组的指针。

创建指向二维数组的指针。

C
潇湘沐 2019-07-04 13:39:01
创建指向二维数组的指针。我需要一个指向静态二维数组的指针。这是怎么做的?static uint8_t l_matrix[10][20];void test(){    uint8_t **matrix_ptr = l_matrix; //wrong idea }我会犯各种各样的错误,比如:警告:来自不兼容指针类型的赋值下标值既不是数组也不是指针。错误:使用灵活数组成员无效
查看完整描述

3 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

充分明白吗,你掌握以下概念:

数组不是指针!

首先(它已经被传得够多了),数组不是指针..相反,在大多数使用中,它们会“衰变”到第一个元素的地址,而第一个元素可以分配给指针:

int a[] = {1, 2, 3};int *p = a; // p now points to a[0]

我假设它是这样工作的,这样就可以在不复制所有内容的情况下访问数组的内容。这只是数组类型的行为,并不意味着它们是相同的。



多维阵列

多维数组只是以编译器/机器能够理解和操作的方式对内存进行“分区”的一种方式。

例如,int a[4][3][5]=包含整数大小内存的4*3*5(60)块的数组。

与使用相比的优势int a[4][3][5]对平原int b[60]它们现在是“分区的”(如果需要的话,可以更容易地使用它们的“块”),并且程序现在可以执行绑定检查。

事实上,int a[4][3][5]存储一点儿没错喜欢int b[60]在记忆中-不同的是,程序现在管理它就好像它们是不同大小的实体(具体来说,是由三组五人组成的四组)。

记住:两者都是int a[4][3][5]int b[60]内存是相同的,唯一的区别是应用程序/编译器是如何处理它们的。

{
  {1, 2, 3, 4, 5}
  {6, 7, 8, 9, 10}
  {11, 12, 13, 14, 15}}{
  {16, 17, 18, 19, 20}
  {21, 22, 23, 24, 25}
  {26, 27, 28, 29, 30}}{
  {31, 32, 33, 34, 35}
  {36, 37, 38, 39, 40}
  {41, 42, 43, 44, 45}}{
  {46, 47, 48, 49, 50}
  {51, 52, 53, 54, 55}
  {56, 57, 58, 59, 60}}

从这一点,您可以清楚地看到,每个“分区”只是一个数组,程序保持跟踪。



句法

现在,数组在语法上不同于指针。..具体来说,这意味着编译器/机器将以不同的方式对待它们。这看起来似乎是一个没有头脑的人,但看看这个:

int a[3][3];printf("%p %p", a, a[0]);

上面的示例两次打印相同的内存地址,如下所示:

0x7eb5a3b4 0x7eb5a3b4

但是,只有一个可以直接分配给指针。:

int *p1 = a[0]; // RIGHT !int *p2 = a; // WRONG !

为什么不能 a 分配给指针,但是 a[0] 能,会,可以?

简单地说,这是多维数组的结果,我将解释为什么:

在‘a我们仍然看到,我们还有另一个“维度”值得期待。在‘a[0]然而,我们已经进入了最高维,所以就程序而言,我们只是在看一个正常的数组。

你可能会问:

为什么数组在为数组创建指针方面是多维的?

最好这样想:

多维数组的“衰变”不只是地址,而是带有分区数据的地址(也就是它仍然理解它的底层数据是由其他数组组成的),它由第一个维度之外的数组设置的边界组成。

这个“分区”逻辑不可能存在于指针中,除非我们指定它:

int a[4][5][95][8];int (*p)[5][95][8];p = a; // p = *a[0] // p = a+0

否则,数组的排序属性的意义就丧失了。

还请注意圆括号的用法。*pint (*p)[5][95][8]-也就是说,我们使用这些边界来创建指针,而不是使用这些边界的指针数组:int *p[5][95][8]



结语

让我们回顾一下:

  • 如果数组在使用的上下文中没有其他用途,则它们将衰减为地址。
  • 多维数组只是数组的数组,因此,“腐朽”地址将承担“我有子维度”的负担。
  • 维度数据不能存在于指针中

    除非你把它给它.

简单地说:多维数组衰减到具有理解其内容的能力的地址。


查看完整回答
反对 回复 2019-07-04
?
侃侃无极

TA贡献2051条经验 获得超10个赞

G‘day,

宣言

static uint8_t l_matrix[10][20];

为20个单元8_t位置的10行预留了存储空间,即200 uint 8_t大小的位置,每个元素通过计算20 x行+列来查找。

所以

uint8_t (*matrix_ptr)[20] = l_matrix;

给您所需的,并指向数组第一行的列零元素?

编辑:再想一想,数组的名称,顾名思义,不是一个指针吗?也就是说,数组的名称是第一个元素的位置的同义词,即l_Matrix[0][0]?

编辑2:正如其他人所提到的,评论空间太小,不宜进一步讨论。总之:

typedef uint8_t array_of_20_uint8_t[20];array_of_20_uint8_t *matrix_ptr = l_matrix;

不为所述数组提供任何存储分配。

如上文所述,按照标准的定义,声明:

static uint8_t l_matrix[10][20];

预留了200个uint 8_t类型的顺序位置。

引用使用表单语句的l_矩阵:

(*l_matrix + (20 * rowno) + colno)

将提供在行中找到的colno‘th元素的内容。

所有指针操作都会自动考虑指向对象的大小。-K&R第5.4节,第103页

如果在当前对象的存储中涉及到任何填充或字节对齐转换,情况也是如此。编译器将根据这些情况自动调整。根据C ANSI标准的定义。

HTH

干杯,


查看完整回答
反对 回复 2019-07-04
  • 3 回答
  • 0 关注
  • 798 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信