【问题标题】:Dereferencing through pointer and incrementing gives a different value and decrements it instead C++通过指针取消引用和递增给出不同的值并递减它而不是 C++
【发布时间】:2023-03-19 04:37:01
【问题描述】:

我试图用 C++ 中的指针做一些实验,我确实有点理解优先级的概念,但是下面的程序在我的脑海中混杂在一起,无法理解

代码:

#include <iostream>
using namespace std;

int main() {

    int x = 9;  
    int* ptr = &x;

cout << "The value of x is " << x << endl << "The value of ptr is " << ptr << endl << *ptr << endl << (*ptr)++ << endl << (*ptr)++ << endl << (*ptr)++ << endl;

    return 0;
}

在这个程序中给 x 的初始值为 9,我希望编译器给我 x 的值为 9,然后使用指针递增它,所以我希望答案为 9,Address,9 ,10,11 ,12 但我在每个编译器中得到的答案是 x 的值是 12 而其余的就像这样 12,Address,11,10,9 请帮助我理解这是 C++ 的新手

【问题讨论】:

  • 使用++(*ptr) 而不是(*ptr)++ 来达到你想要的结果。 ++x 递增 x 的值,然后返回新的递增值,而 x++ 递增但返回以前的值。根据您的问题,您希望拥有++x 的行为。

标签: c++ pointers increment operator-precedence decrement


【解决方案1】:

这与优先级无关,而是与评估顺序有关。您假设评估顺序是从左到右,但事实并非如此。如您所见,就您而言,它是从右到左的。

然而,这是 C++ 发生变化的一个领域。在 C++17 版本中,上述表达式的规则发生了变化,以保证从左到右的求值顺序。因此,如果可以,请使用强制版本 C++17 的编译器选项,您应该会看到结果发生变化。

并不能保证从左到右的评估顺序,例如给定 A + B,它仍然可以是 A 在 B 之前或 B 在 A 之前。完整的详细信息可以找到 here

【讨论】:

    【解决方案2】:

    使用++(*ptr) 而不是(*ptr)++ 来达到你想要的结果。

    ++x 递增 x 的值,然后返回新的递增值,而 x++ 递增 x 但返回 x 的先前值(副本)。

    根据您对9, Address, 9, 10, 11, 12 的期望,您确实希望拥有++x 的行为,因此需要使用++(*ptr)

    您可以在here online 看到更正的代码。

    更新

    事实上,即使使用预增量 ++(*ptr) 在不同的编译器上表现不同,它似乎也是相同的代码,我的 MSVC 2015 和 2019 输出 12 addr 12 12 12 12 如果我在 MSVC 中使用 /std:c++latest 标志,那么输出是正确的预期9 addr 9 10 11 12,所以C++11 或更高版本中的行为发生了变化。

    因此这意味着此类表达式的行为是未定义的,这意味着它在不同的编译器上是不同的,甚至可能是随机的。

    因此,如果您希望在所有版本的编译器中兼容,则绝对需要避免使用此类表达式。或者对 MSVC 使用 /std:c++latest,对其他编译器使用类似标志,以强制使用最新的 C++ 标准。

    为避免出现问题,您可以将递增的结果存储到单独的变量或数组中,然后将其输出到cout

    【讨论】:

    • 但是为什么当我打印 x 时它在开始时给出 12 ?它应该至少在开始时给出 9,因为在那个阶段没有与指针混合?
    • 我在 Visual Studio 和 DevC++ 上运行了你的代码,它仍然提供和以前一样的东西,没有变化
    • @AliM 可能您有一些旧版本或非常不常见的编译器变体,它从右到左或其他顺序评估 &lt;&lt; 运算符。您可以单击我答案中的最后一个链接,您会看到像Clang 这样的通用编译器会以您预期的方式输出。我建议您使用最新的编译器版本和常见的编译器之一,例如 MS Visual StudioGCCCLang
    • @AliM 你使用什么样的视觉工作室?什么版本?我可能会检查我 PC 上的 20152019 版本。
    • @AliM 是的,我很抱歉,事实上MSVC 在 2015 年和 2019 年都显示了完全糟糕的结果。所以这意味着这种表达式的这种行为是未定义的,这意味着它对于不同的编译器可以是随机的!所以唯一要做的就是不要在cout &lt;&lt; ... 中使用++xx++,您应该单独执行此增量,然后才将结果值输出到cout。如果在不同的编译器上不同,你需要避免这样的表达式。
    【解决方案3】:

    这是undefined behavior

    更多详细信息,可以到这个帖子:What made i = i++ + 1; legal in C++17?

    【讨论】:

    • @user4581301 我发了更详细的帖子
    猜你喜欢
    • 2018-09-18
    • 2015-10-15
    • 2021-03-04
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多