关于C中指针递减的困惑
Confusion about pointer decrement in C
考虑以下程序:(查看现场演示 here)
#include <stdio.h>
int main(void)
{
char c[]={'s','h','r','e','y','a','[=10=]'};
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]);
时只得到最后一个字符作为输出。
你做作业的时候
ptr=&c[5];
您使 ptr
指向数组的 fifth
元素,即 a
。现在在循环中你正在打印 ptr[i]
.
让我们从循环的开头开始,看看它打印了什么。
*(ptr+5)
,远远超出数组 c[]
.
{'s','h','r','e','y','a','[=11=]'};
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 G G G G //G -> Garbage
^ ^
ptr (ptr+5)
类似,这会继续,直到 i
是 0
,最后一次迭代,即 *(ptr+0)
。它打印 a
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]);
}
许多其他方法可以做到这一点..
赋值 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 的地址。
问题是这部分代码:
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]);
考虑以下程序:(查看现场演示 here)
#include <stdio.h>
int main(void)
{
char c[]={'s','h','r','e','y','a','[=10=]'};
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]);
时只得到最后一个字符作为输出。
你做作业的时候
ptr=&c[5];
您使 ptr
指向数组的 fifth
元素,即 a
。现在在循环中你正在打印 ptr[i]
.
让我们从循环的开头开始,看看它打印了什么。
*(ptr+5)
,远远超出数组 c[]
.
{'s','h','r','e','y','a','[=11=]'};
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 G G G G //G -> Garbage
^ ^
ptr (ptr+5)
类似,这会继续,直到 i
是 0
,最后一次迭代,即 *(ptr+0)
。它打印 a
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]);
}
许多其他方法可以做到这一点..
赋值 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 的地址。
问题是这部分代码:
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]);