指针算术递增修复后/修复前

Pointer Arithmetic Incrementing post/pre-fix

本文关键字:指针      更新时间:2023-10-16

我很难理解下面一段特定代码的逻辑。

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++运算符的优先级有关,但这对我来说毫无意义

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

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

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

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


另一种看它的方式,你从开始

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

然后执行(*i_ptr)++,该操作会增加i_ptr所指向的值:

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

然后执行*i_ptr++,它首先取消引用i_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

CCD_ 16指向CCD_。因此,在下一行中,当您在再次获得22:之前打印一个元素时

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

现在CCD_ 19仍然指向CCD_

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

这与以下三行有关:

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<lt*(i_ptr-1)<lt;std::endl;//22

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

最后,我们这样做:

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

上面写着"打印出i_ptr正在查看的内容。"由于我们正在查看4,并且已经查看了一段时间,所以我们在这里看到了这一点。