我遇到了一个有竞争性的问题,它询问以下代码的输出:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
我阅读了这个主题:C中是否允许使用负数索引? 但是我不清楚负号如何将数组按相反的顺序生成,即4, 3, 2, 1, 0
。
我遇到了一个有竞争性的问题,它询问以下代码的输出:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
我阅读了这个主题:C中是否允许使用负数索引? 但是我不清楚负号如何将数组按相反的顺序生成,即4, 3, 2, 1, 0
。
首先,回想一下在C语言中,表达式ptr [index]
的意思与*(ptr + index)
是相同的。
现在让我们再次看一下您的表达式:ptr
在循环之前设置为a+4
; 然后你对它应用了一个负的i
索引。因此,等价的指针算术表达式如下:
printf("%d", *(a+4-i));
这个表达式反向迭代数组,产生您看到的结果。
a[x]
for(ptr = a+4, i=0; i <=4; i++)
指针ptr
被设置为a+4
。也可以以下面的方式完成
ptr = &a[4];
printf( "%d\n", *ptr );
你将得到4
。这是指针指向数组的最后一个元素。
循环中使用了表达式ptr[-i]
。当i等于0时,它相当于ptr [0]
或简单地写成*ptr
,输出的是数组的最后一个元素。
当i等于1时,表达式ptr [-i]
等同于a [4-1]
或简单地写成a[3]。当i等于2时,表达式ptr[-i]等同于a [4-i]
即a [4-2]
,而a[4-2]又等于a [2]
,以此类推。
所以你会得到
4321
a+4
会给出指向 a
的第五个元素的指针。因此,ptr
指向那个位置。i
从0递增到(包括)4。ptr[-i]
等同于 *(ptr - i)
(根据定义)。因此,由于 i
是0,ptr
是 a+4
,它等同于 a+4-0
,然后是 a+4-1
,再然后是 a+4-2
,一直到 a+4-4
,也就是显而易见的等于 a
。ptr[-i]
会衰减为*(ptr + (-i))
。在第一次迭代时,当i = 0
时,ptr[-i]
访问a
数组的最后一个元素,因为最初ptr被设置为等于a + 4
,这意味着-取a
的开始地址并加上4 * sizeof(int)
(因为ptr
的大小为int)。在每个下一次迭代中,当i增加时,将访问数组的前一个元素。*(a + (-i))
写成这样,那么 a 确实会衰变为指向 a 的第一个元素的指针。 - Peter - Reinstate Monica正如我在C/C++的评论中提到的那样
a[b] == *(a+b) == b[a]
printf("%d", *(a + 4 - i));
printf("%d", a[4 - i]);
printf("%d", 4[a - i]);
...
ptr
和索引-i
来计算a[]
中某个元素的指针运算。数组a[]
始终以0
为根,并通过a[n]
对其进行反引用,其中n
小于零是未定义行为。数组不是指针。下面的答案潮解释了指针数学概念。 - WhozCraiga[b]
等同于*(a + b)
等同于b[a]
。 - frogatto