指针表达式:**ptr++, *++*ptr 和 ++**ptr 使用 [英] Pointer expressions: **ptr++, *++*ptr and ++**ptr use

查看:32
本文介绍了指针表达式:**ptr++, *++*ptr 和 ++**ptr 使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 C 指针文献.在其中一张插图中,我遇到了以下代码.

I am trying my hands on a C pointer literature. In one of the illustrations, I encountered the following code.

# include <stdio.h>

int main()
{
     static int a[]={0,1,2,3,4};
     static int *p[]={a, a+1, a+2, a+3, a+4};

     int **ptr;

     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);

     return 0;
}

我收到的输出为.

1 1 1
1 2 2
1 2 3

我在证明此输出的合理性方面遇到了问题.我在副本上做了很多方框,以便于掌握问题.我能够证明输出 1 1 1 是合理的,我的麻烦始于语句 *++*ptr.

I am facing a problem in justifying this output. I made lot of boxes on a copy for easy grasp of the problem. I am able to justify the output 1 1 1, my trouble starts with the statement, *++*ptr.

因为一元运算符是从右到左执行的.因此, *ptr 将首先被处理,然后 ptr 处的值将增加.在这个增量之后,我不确定会发生什么,这本书说以某种方式 p 也增加了指向这个数组中的下一个元素.输出1 2 2只能通过p的递增来实现.

Since, a unary operators are executed from right to left. So, *ptr would be tackled first, then the value at ptr would be incremented. After this increment, I am not sure what happens, the book says that somehow p is also incremented to point to the next element in this array. The output 1 2 2 can only be achieved through the increment of p.

我不确定这种问题是否完全适合 stackoverflow.
我尽力了,浪费了至少 10 页,上面画了框.

I am not sure that this kind of question fits exactly on stackoverflow.
I tried my best, wasted at least 10 pages with boxes drawn over them.

如有任何澄清,我们将不胜感激.

Any clarification would be appreciated.

推荐答案

记住数组名在大多数表达式中很容易衰减为指向第一个元素的指针(阅读一些数组名称不会衰减为指向第一个元素的指针的异常? @H2 巧妙回答CO3).
为了更好地理解,请考虑我的图表:

Remember array name can easily decays into pointer to first element in most expressions (read some exceptions where array name not decaying into a pointer to first element? ably answered by @H2CO3).
For better understanding, consider my diagrams:

首先,假设a按如下方式存储在内存中.

First, suppose a stored in memory as follows.

  a 
+----+----+----+----+---+
|  0 |  1 | 2  | 3  | 4 |
+----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲
  |    |    |    |    | 
  a    a+1  a+2  a+3  a+3

声明 static int *p[] = {a, a+1, a+2, a+3, a+4}; 创建一个新的整数指针数组,具有以下值:

Declaration static int *p[] = {a, a+1, a+2, a+3, a+4}; creates a new array of pointers to integer, with following values:

p[0] == a
p[1] == a + 1
p[2] == a + 2
p[3] == a + 3
p[4] == a + 4

现在,也可以假设 p 存储在内存中,如下所示:

Now, p can also be assume to be stored in memory something like below:

  p
+----+----+----+----+-----+
| a  |a +1| a+2| a+3| a+4 | 
+----+----+----+----+-----+
  ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |
  p    p+1  p+2  p+3  p+4

赋值后 ptr = p; 事情将是这样的:

After assignment ptr = p; things will be something like this:

  p                              a 
+----+----+----+----+-----+    +----+----+----+----+---+
| a  |a +1| a+2| a+3| a+4 |    |  0 |  1 | 2  | 3  | 4 |
+----+----+----+----+-----+    +----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲          ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |          |    |    |    |    | 
  p    p+1  p+2  p+3  p+4        a    a+1  a+2  a+3  a+3
  ptr 


Notice: ptr points to first location in pointer array p[]

表达式:**ptr++;

现在我们在第一个 printf 语句之前考虑表达式 **ptr++;.

  1. ptr 等于 p ,即指针数组中第一个元素的地址.因此,ptr 指向数组中的第一个元素 p[0](或者我们可以说 ptr == &p[0]).

  1. ptr is equals to p that is address of first element in array of pointers. Hence, ptr point to first element p[0] in array (or we can say ptr == &p[0]).

*ptr 表示 p[0]并且因为 p[0]a,所以 *ptra (所以 *ptr == a).

*ptr means p[0] and because p[0] is a, so *ptr is a ( so *ptr == a).

并且因为 *ptra,那么 **ptr 就是 *a ==*(a + 0) == a[0]0.

And because *ptr is a, then **ptr is *a == *(a + 0) == a[0] that is 0.

注意在表达式 **ptr++; 中,我们没有将它的值赋给任何 lhs 变量.
所以 **ptr++; 的效果和 ptr++; == ptr = ptr + 1 = p + 1代码>
这样在这个表达式ptr指向p[1]之后(或者我们可以说ptr == &p[1]).

Note in expression **ptr++;, we do not assign its value to any lhs variable.
So effect of **ptr++; is simply same as ptr++; == ptr = ptr + 1 = p + 1
In this way after this expression ptr pointing to p[1] (or we can say ptr == &p[1]).

打印 1:

在第一个 printf 之前,事情变成了:

Before first printf things become:

  p                              a 
+----+----+----+----+-----+    +----+----+----+----+---+
| a  | a+1| a+2| a+3| a+4 |    |  0 |  1 | 2  | 3  | 4 |
+----+----+----+----+-----+    +----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲          ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |          |    |    |    |    | 
  p    p+1  p+2  p+3  p+4        a    a+1  a+2  a+3  a+3
       ptr 


Notice: ptr is equals to  p + 1 that means it points to p[1]

现在我们可以理解首先 printf:

Now we can understand First printf:

  1. ptr - p 输出 1 因为:
    ptr = p + 1,所以 ptr - p == p + 1 - p == 1

  1. ptr - p output 1 because:
    ptr = p + 1, so ptr - p == p + 1 - p == 1

*ptr - a 输出 1 因为:
ptr = p + 1,所以 *ptr == *(p + 1) == p[1] == a + 1
这意味着: *ptr - a = a + 1 - a == 1

*ptr - a output 1 because:
ptr = p + 1, so *ptr == *(p + 1) == p[1] == a + 1
This means: *ptr - a = a + 1 - a == 1

**ptr 输出 1 因为:
*ptr == a + 1 from point-2
所以 **ptr == *(a + 1) == a[1] == 1

**ptr output 1 because:
*ptr == a + 1 from point-2
So **ptr == *(a + 1) == a[1] == 1

表达式:*++*ptr;

在第一个 printf 之后,我们有一个表达式 *++*ptr;.

我们从上面的第 2 点知道 *ptr == p[1].因此,++*ptr(即 ++p[1])会将 p[1] 增加到 a + 2

As we know from above point-2 that *ptr == p[1]. So, ++*ptr (that is ++p[1]) will increments p[1] to a + 2

再次理解,在表达式 *++*ptr; 中,我们没有将它的值赋给任何 lhs 变量,所以 *++*ptr; 的效果只是++*ptr;.

Again understand, in expression *++*ptr; we don't assign its value to any lhs variable so effect of *++*ptr; is just ++*ptr;.

现在,在第二个 printf 之前,事情变成了:

Now, before second printf things become:

  p                              a 
+----+----+----+----+-----+    +----+----+----+----+---+
| a  |a+2 | a+2| a+3| a+4 |    |  0 |  1 | 2  | 3  | 4 |
+----+----+----+----+-----+    +----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲          ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |          |    |    |    |    | 
  p    p+1  p+2  p+3  p+4        a    a+1  a+2  a+3  a+3
       ptr 


Notice: p[1] became a + 2 

打印 2:

现在我们可以理解第二 printf:

Now we can understand Second printf:

  1. ptr - p 输出 1 因为:
    ptr = p + 1,所以 ptr - p == p + 1 - p == 1

  1. ptr - p output 1 because:
    ptr = p + 1, so ptr - p == p + 1 - p == 1

*ptr - a 输出 2 因为:
ptr = p + 1 所以 *ptr == *(p + 1) == p[1]== a + 2
这意味着: *ptr - a == a + 2 - a == 2

*ptr - a output 2 because:
ptr = p + 1 so *ptr == *(p + 1) == p[1] == a + 2
This means: *ptr - a == a + 2 - a == 2

**ptr 输出 2 因为:
*ptr == a + 2 from point-2
所以 **ptr == *(a + 2) == a[2] == 2

**ptr output 2 because:
*ptr == a + 2 from point-2
So **ptr == *(a + 2) == a[2] == 2

表达式:++**ptr;

现在表达式 ++**ptr; 在第三个 printf 之前.

Expression: ++**ptr;

Now expression ++**ptr; before third printf.

我们从上面的第 3 点知道 **ptr == a[2].所以 ++**ptr == ++a[2] 会将 a[2] 增加到 3

As we know from above point-3 that **ptr == a[2]. So ++**ptr == ++a[2] will increments a[2] to 3

所以在第三个 printf 之前,事情变成了:

So before third printf things become:

  p                              a 
+----+----+----+----+-----+    +----+----+----+----+---+
| a  | a+2| a+2| a+3| a+4 |    |  0 |  1 | 3  | 3  | 4 |
+----+----+----+----+-----+    +----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲          ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |          |    |    |    |    | 
  p    p+1  p+2  p+3  p+4        a    a+1  a+2  a+3  a+3
       ptr 


 Notice: a[2] = 3

打印-3:

现在我们可以理解第三 printf:

Now we can understand Third printf:

  1. ptr - p 输出 1 因为:
    ptr = p + 1 所以 ptr - p == p + 1 - p == 1

  1. ptr - p output 1 because:
    ptr = p + 1 so ptr - p == p + 1 - p == 1

*ptr - a 输出 2 因为:
ptr = p + 1 所以 *ptr == *(p + 1) == p[1]== a + 2
这意味着: *ptr - a = a + 2 - a == 2

*ptr - a output 2 because:
ptr = p + 1 so *ptr == *(p + 1) == p[1] == a + 2
This means: *ptr - a = a + 2 - a == 2

**ptr 输出 3 因为:
*ptr == a + 2 from point-2
所以 **ptr == *(a + 2) == a[2] == 3

**ptr outputs 3 because:
*ptr == a + 2 from point-2
So **ptr == *(a + 2) == a[2] == 3

编辑 注意:两个指针的区别在于类型ptrdiff_t,为此,正确的转换说明符是%td,而不是<代码>%d.

Edit Note: The difference of two pointers has type ptrdiff_t, and for that, the correct conversion specifier is %td, not %d.

补充一点:
我想补充,因为我相信它会对新学习者有所帮助

假设我们有以下两行,在 return 0;

Suppose we have following two lines with one more 4th printf in you code before return 0;

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

可以检查这个工作代码@Codepade,这一行输出2 2 3.

One can check this working code @Codepade , this line outputs 2 2 3.

因为 ptr 等于 p + 1 ,所以 ++ 递增运算后 ptr 变成 p + 2(或者我们可以说 ptr == &p[2]).
在那个双重尊重操作之后 ** ==> **(p + 2) == *p[2] == *(a + 2) == a[2] == 3.
现在,再次因为我们在这个语句中没有任何赋值操作,所以表达式 **++ptr; 的效果就是 ++ptr;.

Because ptr is equals to p + 1 , after increment ++ operation ptr becomes p + 2 (or we can say ptr == &p[2]).
After that double deference operation ** ==> **(p + 2) == *p[2] == *(a + 2) == a[2] == 3.
Now, again because we don't have any assignment operation in this statement so effect of expression **++ptr; is just ++ptr;.

所以表达式**++ptr;之后的东西变成如下图:

So thing after expression **++ptr; becomes as below in figure:

  p                              a 
+----+----+----+----+-----+    +----+----+----+----+---+
| a  | a+2| a+2| a+3| a+4 |    |  0 |  1 | 3  | 3  | 4 |
+----+----+----+----+-----+    +----+----+----+----+---+
  ▲    ▲    ▲    ▲    ▲          ▲    ▲    ▲    ▲    ▲
  |    |    |    |    |          |    |    |    |    | 
  p    p+1  p+2  p+3  p+4        a    a+1  a+2  a+3  a+3
            ptr 

 Notice: ptr is equals to  p + 2 that means it points to p[2] 

Print-4:

考虑到 Forth printf 我添加的问题:

Considering Forth printf I added in question:

  1. ptr - p 输出 2 因为:
    ptr = p + 2 所以 ptr - p == p + 2 - p == 2

  1. ptr - p output 2 because:
    ptr = p + 2 so ptr - p == p + 2 - p == 2

*ptr - a 输出 2 因为:
ptr = p + 2 所以 *ptr == *(p + 2) == p[2]== a + 2
这意味着: *ptr - a = a + 2 - a == 2

*ptr - a output 2 because:
ptr = p + 2 so *ptr == *(p + 2) == p[2] == a + 2
This means: *ptr - a = a + 2 - a == 2

**ptr 输出 3 因为:
*ptr == a + 2 从上面点 2
所以 **ptr == *(a + 2) == a[2] == 3

**ptr outputs 3 because:
*ptr == a + 2 from above point-2
So **ptr == *(a + 2) == a[2] == 3

这篇关于指针表达式:**ptr++, *++*ptr 和 ++**ptr 使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆