指针表达式:**ptr++, *++*ptr 和 ++**ptr 使用 [英] Pointer expressions: **ptr++, *++*ptr and ++**ptr use
问题描述
我正在尝试使用 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++;
.
ptr
等于p
,即指针数组中第一个元素的地址.因此,ptr
指向数组中的第一个元素p[0]
(或者我们可以说ptr
==&p[0]
).
ptr
is equals top
that is address of first element in array of pointers. Hence,ptr
point to first elementp[0]
in array (or we can sayptr
==&p[0]
).
*ptr
表示 p[0]
并且因为 p[0]
是 a
,所以 *ptr
是 a
(所以 *ptr
== a
).
*ptr
means p[0]
and because p[0]
is a
, so *ptr
is a
( so *ptr
== a
).
并且因为 *ptr
是 a
,那么 **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:
ptr - p
输出1
因为:ptr = p + 1
,所以ptr - p
==p + 1 - p
==1
ptr - p
output1
because:
ptr = p + 1
, soptr - 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:
ptr - p
输出1
因为:ptr = p + 1
,所以ptr - p
==p + 1 - p
==1
ptr - p
output1
because:
ptr = p + 1
, soptr - 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:
ptr - p
输出1
因为:ptr = p + 1
所以ptr - p
==p + 1 - p
==1
ptr - p
output1
because:
ptr = p + 1
soptr - 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:
ptr - p
输出2
因为:ptr = p + 2
所以ptr - p
==p + 2 - p
==2
ptr - p
output2
because:
ptr = p + 2
soptr - 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屋!