递增的内存地址如何影响指针

问题描述 投票:3回答:3

我正在寻求有关地址递增如何影响指针的解释。

我通过考虑指针类型了解了C指针如何工作以及如何增加指针。我还是不明白以下情况

int main()
{
    int a[] = {1,2,3,4,5};
    int *p = (int*)(&a+1);
    printf("%d\n%d\n", *(a+1), *(p-1));
    return 0;
}

我希望这条线

int *p = (int*)(&a+1);

使p指向数组a之后的地址,因此我期望输出:

2 

原为a[1]

但是输出是unknown_number-因为我不知道哪个int在(&a+1)之后4个字节

实际结果是:

2

5

为什么p似乎直接指向a之后的内存?

我困惑的根源是什么?

c pointers memory memory-management pointer-arithmetic
3个回答
2
投票

两个基本概念:

  • 除了是sizeof或一元&运算符的操作数,还是用于初始化声明中的字符数组的字符串文字,expression类型为“ N元素数组” T“的值将被转换(“衰变”)为类型为“ T的指针”的表达式,该表达式的值将为数组第一个元素的地址。

  • 向“指向T的指针”类型的表达式中加1会产生紧随当前对象之后的T类型的对象的地址。 IOW,如果p指向4字节int,则p+1指向紧随其后的int。如果p指向int的5元素数组,则p+1指向紧随其后的int的下一个5元素数组。这就是数组索引的工作方式-下标操作a[i]定义为*(a + i)。给定起始地址a(指针表达式或衰减到指针的数组表达式),请在该地址后找到第iobject的地址,然后取消对结果的引用。

因此,如果您有声明

int a[] = {1, 2, 3, 4, 5};

那么,以下为真:

  • expression a的类型为“ int的5元素数组”(int [5])-如果表达式不是sizeof的操作数或一元&运算符,它“衰减”以键入“指向int的指针”(int *),其值是数组第一个元素的地址(&a[0])。

  • 表达式*(a + 1)a[1]相同,并且求值为数组(2)中的第二个对象。

  • 表达式&a + 1具有类型int (*)[5],并在int之后产生a的5元素数组的起始地址。该表达式的类型转换为int *并分配给p

  • 表达式p的类型为int *-从中减去1会得出int紧接在前的p对象的地址,该地址恰好是a的最后一个元素。

图解:

   +–––+
a: | 1 |
   +–––+
   | 2 | <–– a + 1
   +–––+
   | 3 |
   +–––+
   | 4 |
   +–––+
   | 5 | <–– p - 1
   +–––+
   | ? | <–– p (&a + 1)
   +–––+

4
投票

因此,在此示例中,&a的类型为int(*)[5]。当您向其添加1时,它实际上会添加sizeof(int[5])-因为这是指针算术的工作方式,因此添加偏移量将指向的类型的大小乘以偏移量。这就是使p成为a的最后一个元素之后的方式,然后将其强制转换为int*,因此现在您有了一个指针,该指针指向a的最后一个元素之后的地址处的整数。 。因此,从中减去1可以得到a的最后一个元素。


1
投票

您可以将数组a用作指向int int *的指针。但是对于&a来说,这是不一样的,它是一个指向5个整数的数组的指针:&a + 1会将5个整数的大小添加到该指针。

© www.soinside.com 2019 - 2024. All rights reserved.