gpt4 book ai didi

c - 指针表达式:** ptr++,*++ * ptr和++ ** ptr使用

转载 作者:太空狗 更新时间:2023-10-29 16:22:59 24 4
gpt4 key购买 nike

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

# 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语句。

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

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

任何澄清将不胜感激。

最佳答案

请记住,在大多数表达式中,数组名称很容易衰减为指向第一个元素的指针(请阅读@ exceptions where array name not decaying into a pointer to first element?适当回答的一些H2CO3)。
为了更好地理解,请考虑我的图:

首先,假设如下存储在内存中的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 ++;

现在我们在第一个printf语句之前考虑表达式 **ptr++;
  • ptr等于p,它是指针数组中第一个元素的地址。
    因此,ptr指向数组中的第一个元素p[0](或者我们可以说ptr == &p[0])。
  • *ptr表示p[0] 并且因为p[0]a,所以*ptra(因此*ptr == a)。
  • 并且因为*ptra,所以**ptr*a == *(a + 0) == a[0]就是0
  • 注意表达式**ptr++;中,我们没有将其值分配给任何lhs变量。
    因此**ptr++;的效果与ptr++; == ptr = ptr + 1 = p + 1完全相同
    这样,在此表达式之后,ptr指向p[1](或者我们可以说ptr == &p[1])。

  • 打印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]

    现在我们可以了解 第一个 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 ==点2的a + 1 所以**ptr == *(a + 1) == a[1] == 1

  • 表达式:* ++ * ptr;

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

    从第二点我们知道 *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 + 1,所以*ptr == *(p + 1) == p[1] == a + 2这意味着:*ptr - a == a + 2 - a == 2
  • **ptr输出2的原因是:
    *ptr ==点2的a + 2 所以**ptr == *(a + 2) == a[2] == 2

  • 表达式:++ ** ptr;

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

    从上面的第三点我们知道 **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 + 1,所以*ptr == *(p + 1) == p[1] == a + 2 这意味着:*ptr - a = a + 2 - a == 2
  • **ptr输出3,因为:*ptr ==点2的a + 2 所以**ptr == *(a + 2) == a[2] == 3

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

    另外一点:
    我希望补充一下,因为我相信这将对新学习者有所帮助

    假设我们在后面两行中在 return 0;之前的代码中再加上一个4th printf
    **++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 + 2,所以*ptr == *(p + 2) == p[2] == a + 2 这意味着:*ptr - a = a + 2 - a == 2
  • **ptr输出3,因为:*ptr ==从第2点开始的a + 2 所以**ptr == *(a + 2) == a[2] == 3
  • 关于c - 指针表达式:** ptr++,*++ * ptr和++ ** ptr使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17752549/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com