指针算术递增 post/pre-fix

Pointer Arithmetic Incrementing post/pre-fix

我无法理解下面一段特定代码的逻辑。

int i[] = { 21, 4, -17, 45 };

int* i_ptr = i;

std::cout << (*i_ptr)++ << std::endl;   // 21

std::cout << *i_ptr << std::endl;       // 22

std::cout << *i_ptr++ << std::endl;     // 22

std::cout << *(i_ptr - 1) << std::endl; // 22

std::cout << *i_ptr << std::endl;       // 4

std::cout << ++*i_ptr << std::endl;     // 5

std::cout << *++i_ptr << std::endl;     // -17

system("pause");

我的问题是这段代码是如何从 22...

std::cout << *(i_ptr - 1) << std::endl; // 22

到 4.

std::cout << *i_ptr << std::endl;       // 4

然后到5.

std::cout << ++*i_ptr << std::endl;     // 5

当我第一次浏览这段代码时,我以为 22 只是从 22 到 21。我知道它与 C++ 运算符优先级有关,但这对我来说毫无意义。

表达式 *i_ptr++ 递增 指针 。它指向数组的 second 元素(值为 4)。

这当然意味着i_ptr - 1必须指向i_ptr当前指向的位置之前的元素,即第一个元素(值为22)。

请记住,对于 any 指针或数组 p 和索引 i,表达式 p[i]*(p + 1) 是完全相等。


另一种看待它的方式,你从

开始
+-----+-----+-----+-----+
|  21 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^
|
i_ptr

然后您执行 (*i_ptr)++ 这会增加 i_ptr 指向的值:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^
|
i_ptr

然后你做 *i_ptr++ ,它首先取消引用 oldi_ptr (结果是 22)和 然后 递增指针:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
      ^
      |
      i_ptr

现在你基本上i_ptr[-1]:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^     ^
|     |
|     i_ptr
|
i_ptr - 1

负索引 可以并且定义明确,只要它们不超出范围即可。

已经在这一行之后

std::cout << *i_ptr++ << std::endl;     // 22

i_ptr指向4。因此,在下一行中,当您再次获得 22:

之前打印一个元素
std::cout << *(i_ptr - 1) << std::endl; // 22

现在 i_ptr 仍然指向 4:

std::cout << *i_ptr << std::endl;       // 4
std::cout << (*i_ptr)++ << std::endl;   // 21
//i_ptr points to i[0], which is increased from 21 to 22

std::cout << *i_ptr << std::endl;       // 22
//prints i[0], which is 22

std::cout << *i_ptr++ << std::endl;     // 22
//prints i[0] and increments i_ptr to point to i[1]

std::cout << *(i_ptr - 1) << std::endl; // 22
//prints i[0], i_ptr points to i[1], so i_ptr - 1 points to i[0]

std::cout << *i_ptr << std::endl;       // 4
//prints i[1], which is 4

std::cout << ++*i_ptr << std::endl;     // 5
//prints the incremented i[1], which was 4 and is 5 now

std::cout << *++i_ptr << std::endl;     // -17
//increment i_ptr to point to i[2] and prints the value

这与这三行有关:

std::cout << *i_ptr++ << std::endl;     // 22
std::court << *(i_ptr - 1) << std::endl; // 22
std::cout << *i_ptr << std::endl;       // 4

事情是这样的:

std::cout << *i_ptr++ << std::endl;     // 22

在这里,这被解释为*(i_ptr++),意思是“将ptr向前推进指向下一个元素,然后将指针返回到i_ptr曾经指向的位置并推导它。 ”换句话说,在该行执行完毕后,指针 ptr 指向元素 4,但该行打印 22,因为那是 ptr 曾经指向的位置。这很重要,因为这意味着我们已经改变了我们正在寻找的地方,即使输出没有立即暗示这一点。

我们看下一行:

std::cout << *(i_ptr - 1) << std::endl; // 22

这表示“打印出 i_ptr 查找位置之前的元素。”请记住,此时 i_ptr 正在查看 4,因此通过查看列表中的一个元素,我们会看到值 22。

最后,我们这样做:

std::cout << *i_ptr << std::endl;       // 4

这表示“打印出 i_ptr 正在查看的任何内容。”因为我们正在看 4 - 已经有一段时间了 - 这就是我们在这里看到的。