请记住,在大多数表达式中,数组名称很容易衰减为指向第一个元素的指针(阅读一些异常,其中数组名称没有衰减为指向第一个元素的指针? @ H 2 CO 3巧妙地回答了)。
为了更好地理解,请考虑我的图表:
首先,假设a存储在内存中如下。
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};创建了一个指向整数的新指针数组,具有以下值:
p[0] == a
p[1] == a + 1
p[2] == a + 2
p[3] == a + 3
p[4] == a + 4
现在,p也可以假设存储在内存中,如下所示:
p
+----+----+----+----+-----+
| a |a +1| a+2| a+3| a+4 |
+----+----+----+----+-----+
▲ ▲ ▲ ▲ ▲
| | | | |
p p+1 p+2 p+3 p+4
分配后ptr = p;的事情将是这样的:
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++;
现在我们考虑**ptr++;第一个 printf 语句之前的表达式。
ptr等于是 p指针数组中第一个元素的地址。因此,ptr指向p[0]数组中的第一个元素(或者我们可以说ptr== &p[0])。
*ptr意味着p[0]
并且因为p[0]是 a,所以 *ptr是a(所以*ptr== a)。
并且因为*ptris a, then **ptris *a== *(a + 0)== a[0]那就是0.
请注意,在表达式中**ptr++;,我们不会将其值分配给任何 lhs 变量。
所以 of 的效果就和== =**ptr++;一样,
就是在这个表达式指向之后(或者我们可以说== )。ptr++;ptr = ptr + 1p + 1
ptrp[1]ptr&p[1]
打印一:
在第一次 printf 事情变成:
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]
现在我们可以理解First printf:
ptr - p输出1因为:
ptr = p + 1, 所以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输出1因为:
*ptr==a + 1从第 2 点开始
所以**ptr== *(a + 1) == a[1]==1
表达式:**++*ptr;
在第一个 printf 之后,我们有一个表达式 *++*ptr;。
正如我们从上面第 2 点知道的那样*ptr== p[1]。因此,++*ptr(即++p[1])将p[1]增加到a + 2
再次理解,在表达式中*++*ptr;我们没有将它的值赋给任何 lhs 变量,所以效果 *++*ptr;就是++*ptr;.
现在,在第二个 printf 事情变成:
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 了:
ptr - p输出1因为:
ptr = p + 1, 所以ptr - p== p + 1 - p==1
*ptr - a输出2因为:
ptr = p + 1so *ptr == *(p + 1)== p[1]==a + 2
这意味着:*ptr - a== a + 2 - a==2
**ptr输出2因为:
*ptr==a + 2从第 2 点开始
所以**ptr== *(a + 2) == a[2]==2
表达式:++**ptr;
现在++**ptr;在第三个 printf 之前表达。
正如我们从上面第 3 点知道的那样**ptr== a[2]。所以++**ptr==++a[2]将a[2]增加到3
所以在第三个 printf 事情变成:
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 了:
ptr - p输出1因为:
ptr = p + 1所以ptr - p== p + 1 - p==1
*ptr - a输出2因为:
ptr = p + 1so *ptr == *(p + 1)== p[1]==a + 2
这意味着:*ptr - a= a + 2 - a==2
**ptr输出3因为:
*ptr==a + 2从第 2 点开始
所以**ptr== *(a + 2) == a[2]==3
编辑注意:两个指针的区别是 type ptrdiff_t,为此,正确的转换说明符是%td, not %d。
补充一点:
我想补充一下,因为我相信这对新学习者会有帮助
假设我们之前在您的代码中有以下两行,其中还有一个 4 th printfreturn 0;
**++ptr; // additional
printf("%d %d %d\n", ptr-p, *ptr-a, **ptr); // fourth printf
可以检查此工作代码@Codepade,此行输出2 2 3。
表达式:**++ptr;
因为ptr等于p + 1,所以在自增++操作之后ptr就变成了p + 2 (或者我们可以说ptr== &p[2])。
在双重尊重操作之后** ==> **(p + 2) == *p[2]== *(a + 2)== a[2]== 3。
现在,再次因为我们在这个语句中没有任何赋值操作,所以表达式**++ptr;的效果只是++ptr;.
所以表达式后的东西**++ptr;变成了下图:
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]
打印 4:
考虑到我在问题中添加的Forth printf:
ptr - p输出2因为:
ptr = p + 2所以ptr - p== p + 2 - p==2
*ptr - a输出2因为:
ptr = p + 2so *ptr == *(p + 2)== p[2]==a + 2
这意味着:*ptr - a= a + 2 - a==2
**ptr输出3因为:
*ptr==a + 2从上面第 2 点开始
所以**ptr== *(a + 2) == a[2]==3