既然您似乎对它完全陌生,那么让我用简单的术语向您解释一下,而不是进行严格的解释。
你看,对于你上面的程序,a
并且&a
会有相同的数值,我相信这就是你的全部困惑所在。你可能想知道如果它们相同,下面应该在这两种情况下给出下一个地址a
,过去指针算法:
(&a+1) and (a+1)
但事实并非如此!!数组的基地址(a
这里)和数组的地址不一样! a
并且&a
可能在数字上相同,但它们不是同一类型。a
是类型char*
,&a
而是类型char (*)[5]
,&a
即是指向(地址)和大小为 5 的数组的指针。a
但正如您所知,是数组的第一个元素的地址。从数字上看,它们与您看到的相同使用下面的^进行插图。
但是当你增加这两个指针/地址时,即 as(a+1)
和(&a+1)
,算术是完全不同的。虽然在第一种情况下它“跳转”到数组中下一个元素的地址,在后一种情况下它跳转 5 个元素为这就是 5 个元素的数组的大小!。现在明白了?
1 2 3 4 5
^ // ^ stands at &a
1 2 3 4 5
^ // ^ stands at (&a+1)
1 2 3 4 5
^ //^ stands at a
1 2 3 4 5
^ // ^ stands at (a+1)
以下将给出有关未指定数组边界的错误,因为未明确指定如下大小意味着程序将不知道遇到 (&a+1) 之类的情况时要“跳转”到多少个元素。
char a[]={1,2,3,4,5};
char *ptr=(char *)(&a+1); //(&a+1) gives error as array size not specified.
现在到你将指针/地址递减为的部分(ptr-1)
。在第一种情况下,在你来到递减部分之前,你应该知道在它上面的语句中发生了什么,它被强制转换为 type char*
:
char *ptr=(char *)(&a+1);
这里发生的是你“剥离”原来type
的(&a+1)
类型char (*)[5]
,现在将其转换为与数组的基地址char*
相同的类型。(再次注意数组基地址a
之间的区别和数组的地址。所以在上述语句中的强制转换和赋值之后,然后是递减,现在在数组的最后一个元素之后给出内存位置,即。printf()
ptr
5
1 2 3 4 5
^ // ^ stands at location of 5, so *ptr gives 5
ptr
因此,当您在递减指针后取消引用指针时,它会按预期*(ptr-1)
打印值。5
最后,将其与打印的第二种情况进行1
对比。看看我使用符号^给出的插图。当您增加a
asa+1
时,它指向数组的第二个元素,即2
您已将此地址分配给。因此,ptr
当您将其减少ptr
as时(ptr-1)
,它会跳回一个元素,现在指向数组的第一个元素,即 1
。所以ptr
在第二种情况下取消引用给出1
.
1 2 3 4 5
^ // ^ stands at address of 1, so *ptr gives 1
希望这一切都清楚了。