【问题标题】:Unexpected behaviour found while dealing with a pointer to an array处理指向数组的指针时发现意外行为
【发布时间】:2018-05-22 08:56:48
【问题描述】:

看下面给出的代码:

#include<stdio.h>
int main()
{
     int (*p)[3];
     int a[3]={10,11,12};
     p=&a;
     printf("%d\n", *p[0]);
     printf("%d\n", *p[1]);
     printf("%d\n", *p[2]);
     return 0;
}

printf("%d\n", *p[0]);打印 10 这是预期的。

但是 printf("%d\n", *p[1]);不打印 11。

并且 printf("%d\n", *p[2]);不打印 12。

为什么?这背后的原因是什么?

【问题讨论】:

  • *p[k]*(p[k]),而不是 (*p)[k]
  • 您知道p 是一个由三个指针组成的数组,其中一个指向a[0],另一个指向未知内存?
  • 使用简单的指针 (int *p;) 并递增指针以显示数组的其他值。
  • 没有。我认为 p 是一个由三个指针组成的数组,其中一个指向 a[0],一个指向 a[1],一个指向 a[2]。我可能弄错了。但是为什么除了 p[0] 之外的其他指针都指向未知内存呢? @Kami Kaze

标签: c arrays pointers


【解决方案1】:

运算符优先级。 [] 的优先级高于 *,因此当您编写 *p[0] 时,它与 (*(*(p + 0))) 相同 - 您对数组指针进行指针运算。

这意味着例如p[1] 给你p + 3*sizeof(int) 字节的地址,这是访问数组越界。

正确的代码应该是:

 printf("%d\n", (*p)[0]);
 printf("%d\n", (*p)[1]);
 printf("%d\n", (*p)[2]);

【讨论】:

  • 值得指出的是,C 声明的设计是为了反映它们的用法。因此,如果您需要将 p 声明为 int (*p)[3],这可能也是您需要使用它的方式。即foo = (*p)[0]
【解决方案2】:

*p[k]*(p[k]),而不是 (*p)[k]

您得到*p[0] 的预期结果可以解释为它与p[0][0] 相同,并且您将零放入哪个顺序并不重要。

但是,p[1][0] (*p[1]) 与 p[0][1] ((*p)[1]) 不同。
(它甚至是未定义的,因为p[1] 不存在。)

【讨论】:

    【解决方案3】:

    int (*p)[3]; 是指向int 的指针数组。

    int a[3]={10,11,12};int 的数组。数组和指针共享很多属性。例如,您可以对指针使用数组表示法。

    让我们获取一个普通指针int *p = a,它与int *p = &amp;a[0] 相同。现在指针指向数组的第一个元素。并且可以和数组一样使用。

     printf("%d\n", p[0]); //10
     printf("%d\n", p[1]); //11
     printf("%d\n", p[2]); //12
    

    你所做的是获取数组的地址——“指针”这会产生数组第一个元素的地址。因为&amp;a == a

    这将被写入指针数组的第一个元素,让你留下

    p[0] == a
    p[1] == unknown
    p[2] == unknown
    

    通过执行*p[0],您可以获得p (p[0]) 的第一个元素并取消引用它*。 这与*aa[0] 相同。

    但是通过执行*p[1],您会到达一个未知的内存位置(p[1])并取消对它的引用*。这是未定义的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 2016-07-30
      相关资源
      最近更新 更多