关于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)

类似,这会继续,直到 i0,最后一次迭代,即 *(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+5ptr+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]);