【问题标题】:Output of a code- behaviour of & in cc 中 & 的代码行为的输出
【发布时间】:2015-06-23 21:23:19
【问题描述】:

我遇到了一个我无法理解的输出代码。代码是-

int main() 
{       
  int a[] = {1, 2, 3, 4, 5, 6};   

  int *ptr = (int*)(&a+1); 
  printf("%d ", *(ptr-1) ); 
  return 0; 
} 

上面代码的输出是6,但我认为应该是1。请解释为什么是6。

【问题讨论】:

  • 整数是 2 个字节。 &a+1 只是在内存地址中向前移动一个字节......它应该是&a + sizeof(int),基本上。
  • 这在技术上是未定义的行为,因为您从不兼容的指针进行转换,应该是 int *ptr = *(&a+1);
  • @MarcB 不,这将指向出界。
  • @MarcB: int 终于 16位。然而,它可以更多。对于典型的 32 位 CPU,大多数时候是 32 位(4 个八位字节)。

标签: c arrays pointers pointer-arithmetic


【解决方案1】:

在您的问题中,“&a”是整个数组 a[] 的地址。如果我们将 1 加到 &a,我们得到“a[] + sizeof(a) 的基地址”。并且这个值被强制转换为 int *。所以 ptr 指向 6 之后的内存。 ptr 被类型转换为“int *”并打印 *(ptr-1) 的值。由于 ptr 指向 6 之后的内存,所以 ptr – 1 指向 6。

【讨论】:

  • C 中数组的名称给出了第一个元素的地址(sizeof 运算符除外)。向这个地址加 1 得到地址加上数组的 sizeof 类型
  • 第二个元素
  • @DeepakTiwari:自动将数组转换为指针有更多例外。见the standard。这实际上包括您刚刚在答案中给出的原因。
【解决方案2】:

&a 是数组a 的地址。向其添加1 会将其递增到数组之后的一位(添加24 字节)。将运算符 (int*) 转换为 &a+1 到指向 int 类型的指针。 ptr-1 将减少 ptr 4 字节,因此它是数组 a 的最后一个元素的地址。取消引用 ptr - 1 将给出最后一个元素 6

【讨论】:

  • 有趣的是,&aa 在内存中的地址相同。区别在于它们的类型以及它如何反映到指针算法。不错的答案(没有理由不赞成)
  • @GrzegorzSzpetkowski 详细信息“&aa 具有相同的 ”。 &a 没有地址。
【解决方案3】:

是的,因为a 是一个类型为int[6] 的数组。因此,&a 为您提供int (*)[6] 类型。它与指向 int 的指针相同,它是指向 int 数组的指针。

所以,&a + 1 将指针增加一个数组大小,指向数组的最后一个元素。

然后,获取ptr 中的地址并执行-1,将地址减少sizeof(*ptr),即sizeof(int),从而得到数组中最后一个元素的地址。

最后,取消引用该地址,您将获得最后一个元素的值 6。成功。

【讨论】:

    【解决方案4】:

    因为(int*)(&a + 1) 使用整个数组作为基类型,并将数组的 1 个完整大小添加到地址,即添加 24 个字节。

    当您执行 ptr-1 时,因为 ptr 类型是 int,它只会减去 4 个字节。 在进行指针运算时记住指针的类型非常重要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多