首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >创建指向二维数组的指针

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

Stack Overflow用户
提问于 2009-06-27 13:20:43
回答 10查看 249K关注 0票数 130

我需要一个指向静态二维数组的指针。这是怎么做的?

代码语言:javascript
复制
static uint8_t l_matrix[10][20];

void test(){
   uint8_t **matrix_ptr = l_matrix; //wrong idea 
}

我得到了各种各样的错误,比如:

灵活数组警告:来自不兼容指针type

  • subscripted值的赋值既不是数组也不是指针

  • 错误:灵活数组成员

的使用无效

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2009-06-27 13:37:28

在这里,您希望创建一个指向数组第一个元素的指针

代码语言:javascript
复制
uint8_t (*matrix_ptr)[20] = l_matrix;

使用typedef,这看起来更简洁。

代码语言:javascript
复制
typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

然后你就可以再次享受生活了:)

代码语言:javascript
复制
matrix_ptr[0][1] = ...;

当心C中的pointer/array world,这里面有很多混淆。

编辑

在这里查看一些其他答案,因为注释字段太短,无法在那里完成。提出了多种替代方案,但没有展示它们的行为方式。他们是这样做的:

代码语言:javascript
复制
uint8_t (*matrix_ptr)[][20] = l_matrix;

如果修复了错误并添加了操作符&的address-of,如以下代码片段所示

代码语言:javascript
复制
uint8_t (*matrix_ptr)[][20] = &l_matrix;

然后创建一个指向20 uint8_t类型的数组元素的不完整数组类型的指针。

代码语言:javascript
复制
(*matrix_ptr)[0][1] = ...;

因为它是指向不完整数组的指针,所以不能作为快捷方式

代码语言:javascript
复制
matrix_ptr[0][0][1] = ...;

因为索引需要知道元素类型的大小(索引意味着向指针添加一个整数,因此它不适用于不完整的类型)。请注意,这只适用于C,因为T[]T[N]是兼容的类型。C++没有兼容类型的概念,因此它将拒绝该代码,因为T[]T[10]是不同的类型。

以下替代方法根本不起作用,因为当您将数组视为一维数组时,数组的元素类型不是uint8_t,而是uint8_t[20]

代码语言:javascript
复制
uint8_t *matrix_ptr = l_matrix; // fail

下面是一个很好的选择

代码语言:javascript
复制
uint8_t (*matrix_ptr)[10][20] = &l_matrix;

您可以使用以下命令访问它

代码语言:javascript
复制
(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now

它的好处是它保留了外部尺寸的大小。因此,您可以对其应用sizeof

代码语言:javascript
复制
sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20

还有另一个答案,它利用数组中的项是连续存储的这一事实

代码语言:javascript
复制
uint8_t *matrix_ptr = l_matrix[0];

现在,形式上只允许访问二维数组的第一个元素的元素。也就是说,以下条件成立

代码语言:javascript
复制
matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid

matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior

您将注意到它可能适用于10*20-1,但是如果您使用别名分析和其他激进的优化,一些编译器可能会做出可能破坏该代码的假设。话虽如此,我从来没有遇到过编译器在它上面失败过(但话又说回来,我没有在真正的代码中使用过这种技术),甚至C FAQ也包含了这种技术(带有关于其UB‘性的警告),如果您不能更改数组类型,这是拯救您的最后一个选择:)

票数 153
EN

Stack Overflow用户

发布于 2016-01-10 14:21:08

要完全理解这一点,您必须掌握以下概念:

数组不是指针!

首先,数组不是指针,这一点已经宣传得够多了。相反,在大多数情况下,它们“衰减”到它们的第一个元素的地址,该地址可以分配给一个指针:

代码语言:javascript
复制
int a[] = {1, 2, 3};

int *p = a; // p now points to a[0]

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

多维数组

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

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

与普通int b[60]相比,使用int a[4][3][5]的优点是它们现在是“分区的”(如果需要,更容易处理它们的“块”),并且程序现在可以执行边界检查。

实际上,int a[4][3][5]的存储方式与int b[60]在内存中的存储方式完全相同-唯一的区别是程序现在将其作为特定大小的独立实体进行管理(具体地说,是四个组,每组三个,每组五个)。

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

代码语言:javascript
复制
{
  {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}
}

由此,您可以清楚地看到,每个“分区”只是一个程序跟踪的数组。

语法

现在,数组在语法上不同于指针。具体来说,这意味着编译器/机器将以不同的方式对待它们。这看起来可能很简单,但看看这一点:

代码语言:javascript
复制
int a[3][3];

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

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

代码语言:javascript
复制
0x7eb5a3b4 0x7eb5a3b4

然而,只有一个可以被赋值给指针,所以直接

代码语言:javascript
复制
int *p1 = a[0]; // RIGHT !

int *p2 = a; // WRONG !

为什么 a 不能赋值给指针,而 a[0] 可以赋值?

简单地说,这是多维数组的结果,我将解释原因:

在“a”的层面上,我们仍然看到我们有另一个“维度”值得期待。然而,在'a[0]‘级别,我们已经处于最高维度,所以就程序而言,我们只是在查看一个正常的数组。

你可能会问:

对于为数组创建指针而言,如果数组是多维数组有什么关系?

最好是这样想:

来自多维数组的“衰减”不仅仅是一个地址,而是一个具有分区数据的地址(也就是说,它仍然知道它的底层数据是由其他数组组成的),它由超出第一维的数组设置的边界组成。

这个‘分区’逻辑不能存在于一个指针中,除非我们指定它:

代码语言:javascript
复制
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]

结论

让我们回顾一下:

如果没有其他用途,子数据数组就会衰减为地址,因为使用的context

  • Multidimensional数组只是数组的数组-因此,“衰减的”地址将承担“我有子dimensions"

  • Dimension数据不能存在于指针中,除非你将它赋给它。”的负担。

简而言之:多维数组衰减为能够理解其内容的地址。

票数 32
EN

Stack Overflow用户

发布于 2012-02-18 08:13:07

在……里面

代码语言:javascript
复制
int *ptr= l_matrix[0];

你可以像这样访问

代码语言:javascript
复制
*p
*(p+1)
*(p+2)

毕竟,2维数组也存储为1-d。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1052818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档