表达式 *++ptr 与 ++*ptr 有何不同?

0 c pointers increment pointer-arithmetic dereference

有人可以解释为什么在输出中3 4 4打印而不是打印吗4 4 4

#include <stdio.h>

int main(){

    int a[] ={0,1,2,3,4};
    int *p[] = {a,a+1,a+2,a+3,a+4};
    int **ptr= p; 

    ptr++;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    *ptr++;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    *++ptr;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
    ++*ptr;
    printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出

Vla*_*cow 5

对于初学者来说,请注意两个指针的类型不同ptrdiff_t。您不能%d对这种类型的对象使用转换说明符。你必须使用%td. 举例来说

printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);
Run Code Online (Sandbox Code Playgroud)

表达式 *++ptr 与 ++*ptr 有何不同?

这个表情

*++ptr
Run Code Online (Sandbox Code Playgroud)

相当于

*( ++ptr )
Run Code Online (Sandbox Code Playgroud)

也就是说,首先指针递增并指向数组的下一个元素,然后取消引用,提供指向元素的左值。

这个表情

++*ptr
Run Code Online (Sandbox Code Playgroud)

这相当于

++( *ptr )
Run Code Online (Sandbox Code Playgroud)

也就是说,首先取消引用指针,为指向的元素提供左值,然后元素本身递增。

至于显示的代码

   int a[] ={0,1,2,3,4};
   int *p[] = {a,a+1,a+2,a+3,a+4};
   int **ptr= p; 

   ptr++;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   *ptr++;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   *++ptr;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
   ++*ptr;
   printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
Run Code Online (Sandbox Code Playgroud)

那么最初指针ptr指向数组的第一个元素p

   int **ptr= p; 
Run Code Online (Sandbox Code Playgroud)

然后指针递增

   ptr++;
Run Code Online (Sandbox Code Playgroud)

现在它指向数组的第二个元素p

结果这个表达式

ptr-p
Run Code Online (Sandbox Code Playgroud)

产生两个指针之间的元素数量ptr,并且p(在此表达式中,数组指示符转换为指向其第一个元素的指针)等于1

Asptr指向数组中值为 a + 1 的元素,p则表达式

*ptr-a
Run Code Online (Sandbox Code Playgroud)

也产生值1。和表达

**ptr
Run Code Online (Sandbox Code Playgroud)

产生表达式 的值a[1]

这个表达式语句

*ptr++;
Run Code Online (Sandbox Code Playgroud)

事实上相当于

ptr++;
Run Code Online (Sandbox Code Playgroud)

因为指针的解除引用没有副作用。

现在指针指向数组的第三个元素p。还有这个声明

 printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);
Run Code Online (Sandbox Code Playgroud)

输出

2 2 2
Run Code Online (Sandbox Code Playgroud)

再次声明这一点

   *++ptr;
Run Code Online (Sandbox Code Playgroud)

相当于声明

   ++ptr;
Run Code Online (Sandbox Code Playgroud)

因为取消引用没有副作用。现在指针指向数组的第四个元素p

还有这个声明

   printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);
Run Code Online (Sandbox Code Playgroud)

输出

3 3 3
Run Code Online (Sandbox Code Playgroud)

在这份声明中

   ++*ptr;
Run Code Online (Sandbox Code Playgroud)

p指针指向的数组元素(第四个元素)递增ptr。即数组的第四个元素现在等于a+4

所以数组p现在看起来像

int *p[] = { a, a + 1, a + 2, a + 4, a + 4 };
Run Code Online (Sandbox Code Playgroud)

所以这个声明

   printf("%td %td %d\n",ptr-p,*ptr-a,**ptr);
Run Code Online (Sandbox Code Playgroud)

输出

3 4 4
Run Code Online (Sandbox Code Playgroud)