【问题标题】:Why can't a c pointer be treated as an array?为什么不能将 c 指针视为数组?
【发布时间】:2015-09-15 06:24:56
【问题描述】:

在问题Find size of array without using sizeof in C 中,提问者通过获取地址然后将数组索引指定为 1 来将 int 数组视为 int 数组的数组:

int arr[100];
printf ("%d\n", (&arr)[1] - arr);

该值最终成为arr 之后的 100 个元素的“下一个”数组中第一个元素的地址。当我尝试这个类似的代码时,它似乎没有做同样的事情:

int *y = NULL;
printf("y = %d\n", y);
printf("(&y)[0] = %d\n", (&y)[0]);
printf("(&y)[1] = %d\n", (&y)[1]);

我最终得到:

y = 1552652636
(&y)[0] = 1552652636
(&y)[1] = 0

为什么(&y)[1] 不是指向y 之后的int 的“next”指针的地址?

【问题讨论】:

  • 这么多未定义行为的实例……请先阅读初学者的 C 入门指南。这是完全错误的(您对输出的期望也是如此)。
  • 最终,指针不是数组,数组也不是指针,即使它们密切相关。
  • (&arr)[1] - arr 是一个相当有问题的代码......人们不应该编写处于未定义行为边界的代码。
  • 我怀疑你在设置int *y = NULL;后得到了那个输出。

标签: c arrays


【解决方案1】:

这里:

printf("(&y)[1] = %d\n", (&y)[1]);

你先说:取y的地址。然后你说:添加 1 倍于所指向事物大小的字节 - 这是指向 int 的指针,因此可能添加了 4 个字节 - 并取消引用该地址上的任何内容。但是你不知道那个新的内存地址上有什么,你不能/不应该访问它。

【讨论】:

  • 很有可能它会指向堆栈中的随机对象,例如this
  • @MooseBoys:是的,但我现在不确定它是否像 OP 所做的那样很好地定义为 取消引用该地址
【解决方案2】:

数组不是指针,指针也不是数组。

“数组大小”代码计算两个数组之间的距离,这将是一个数组的大小。
您的代码尝试计算两个指针之间的距离,应该是指针的大小。

我认为混淆的根源在于(&y)[1] 是指向inty 之后的“下一个”指针的,而不是它的地址。

它的地址是&y + 1

同理,y地址&y,而(&y)[0] - 或者,等价的*(&y) - 是y值 em>。

(在“数组大小”代码中,(&arr)[1] 也是“下一个”,但由于该值是一个数组,因此它被隐式转换为指向数组第一个元素的指针— &((&array)[1])[0].)

如果你运行这个:

int *y = NULL;
printf("y = %p\n", y);
printf("&y = %p\n", &y + 0);
printf("&y + 1 = %p\n", &y + 1);

输出看起来有点像这样:

y = (nil)
&y = 0xbf86718c
&y + 1 = 0xbf867190

和 0xbf867190 - 0xbf86718c = 4,这对 32 位指针有意义。

访问(&y)[1](即*(&y + 1))是未定义的,可能会导致一些随机垃圾。

【讨论】:

    【解决方案3】:

    感谢您的回答,我认为回答问题的最简单方法是了解每个表达式的值是什么。首先我们必须知道类型,然后我们才能确定值

    我使用 c 编译器通过将值分配给错误的类型(字符)来生成警告,这样我就可以准确地看到它认为的类型是什么。

    给定声明int arr[100](&arr)[1] 的类型是int [100]

    给定声明int *ptr(&ptr)[1] 的类型是int *

    int[100] 的值是数组开始的常量内存地址。我不知道为什么会这样的所有历史。

    另一方面,int * 的值是指针当时恰好持有的任何内存地址。

    所以它们是非常不同的东西。要获取指针开始位置的常量内存地址,您必须取消引用它。所以&(&ptr)[1]int **,它是 int 指针开始的常量内存地址。

    【讨论】:

      猜你喜欢
      • 2012-09-22
      • 2020-11-04
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多