考虑以下计划:(参见现场演示here)
#include <stdio.h>
int main(void)
{
char c[]={'s','h','r','e','y','a','\0'};
char *ptr=c;
for(int i=0;i<6;i++)
printf("%c",ptr[i]);
printf("\n");
char (*s)[7];
s=&c;
for(int i=0;i<6;i++)
printf("%c",(*s)[i]);
printf("\n");
ptr=&c[5]; // ptr points to 6th char of string
for(int i=5;i>=0;i--)
printf("%c",ptr[i]);
}
该计划未给出预期结果。我得到的结果是:
SHREYA
SHREYA
一
但如果我写下最后一个循环,就像下面一样,它可以正常工作。
for(int i=5;i>=0;i--)
printf("%c",c[i]);
我在这里对指针的理解是错误的?为什么在最后一个for循环中写printf("%c",ptr[i]);
时,我只得到最后一个char作为输出。
答案 0 :(得分:6)
完成作业后
ptr=&c[5];
您ptr
指向数组的fifth
元素,即a
。现在在循环内打印ptr[i]
。
让我们从循环的开头开始,看看它打印的内容。
*(ptr+5)
,超出了数组c[]
。
{'s','h','r','e','y','a','\0'};
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 G G G G //G -> Garbage
^ ^
ptr (ptr+5)
类似地,这继续,直到i
为0
,即最后一次迭代,即*(ptr+0)
。在其上打印a
答案 1 :(得分:5)
指定ptr=&c[5];
使ptr
保留字符串第5个元素的地址。
如果您想要访问前面的元素,则需要否定索引来回退字符串。
ptr=&c[5]; // ptr points to 6th char of string
for(int i=4;i>=0;i--)
printf("%c",ptr[-i]);
或者
ptr=&c[5]; // ptr points to 6th char of string
for(int i=-4;i<=0;i++)
printf("%c",ptr[i]);
还请考虑第5个元素被移位4个位置(因为第一个位于偏移0处,从0到4计数有5个符号)。
另一个有效,因为数组c
总是指向元素0的地址。
答案 2 :(得分:3)
使用ptr=&c[5];
,您的指针指向'a'
第一个循环将指向UB,因为它将是'a'+5
的地址,依此类推。
您需要的是:
ptr=&c[5];
for(int i=5;i>=0;i--){
printf("%c",*ptr);
ptr--;
}
或者
ptr=c;
for(int i=5;i>=0;i--){
printf("%c",ptr[i]);
}
许多其他方法......
答案 3 :(得分:3)
问题在于代码的这一部分:
ptr=&c[5]; // ptr points to 6th char of string
for(int i=5;i>=0;i--)
printf("%c",ptr[i],i);
将上述内容更改为:
ptr=&c[5]; // ptr points to 6th char of string
for(int i=5;i>=0;i--)
printf("%c",ptr[i-5],i);
ptr[i]
您可以带一个未定义的引用,因为ptr+5
,ptr+4
等可能无法访问,并且它们不指向数组。
更好的方法是简单地指向数组的基础并打印如下:
ptr=&c[0]; // ptr points to the base address of the char array
for(int i=5;i>=0;i--)
printf("%c",ptr[i]);