【问题标题】:Why the expression *(b++) doesn't evaluate the b++ first?为什么表达式 *(b++) 不首先评估 b++?
【发布时间】:2014-09-25 10:37:55
【问题描述】:

我试图了解括号如何影响表达式中的优先级:

int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
auto b = arr;
std::cout << *(++b) << std::endl;

// output : 1

在这段代码中,我得到了预期的输出,但如果我将其更改为:

std::cout << *(b++) << std::endl;
// output 0 

我得到0 作为输出。由于括号的原因,我认为 b++ 将首先被评估,然后取消引用。看来我错了,然后我完全删除了括号并使用*++b*b++进行测试并得到相同的结果。这是否意味着括号不会影响这种表达式的优先级?为什么这两个表达式的结果是等价的:

*(b + 1) 
*(++b) 

*(b++) 不是这样?

【问题讨论】:

  • 因为这几乎是后缀增量的定义?请解释您认为它应该做什么以及这与前缀增量 (++b) 有何不同。
  • tl;dr b++ == b,括号不会神奇地改变评估结果。
  • @delnan 是的,我知道其中的区别,但这就是我所关心的括号。

标签: c++ pointers operators operator-precedence


【解决方案1】:

确实首先评估b++b++ 递增 b 并返回 bprevious 值,在递增发生之前b++ 的结果和之后b 的值不同。可以把它想象成(使用int 而不是int *,因为引用指针会使签名变得丑陋):

int postfix_increment(int &x) {
    int result = x;
    x = x + 1;
    return result;
}

(除非使用增量值before the next sequence point 是未定义的行为。)

如果您为括号的结果引入一个临时变量,以确保首先对其进行评估,则可能更容易看出差异:

int *tmp = b++;
// At this point, b == tmp + 1!
std::cout << *tmp << std::endl;

【讨论】:

  • 好吧,这很清楚。顺便说一句,我猜你在 tmp 中缺少 *
  • @Selman22 是的,错过了 b 是一个指针,而不是一个 int。幸运的是,解释完全没有区别。
【解决方案2】:

*(b++)相当于存储旧指针,递增指针,解引用旧指针

int* post_increment(int* b) 
{
   int* old = b;
   ++b;
   return old;
}

围绕一个普通指针编写一个精简的迭代器包装器是一个有益的练习。在编写用户定义的迭代器时,上面的post_increment()函数通常写成一个重载的operator++(int)int 参数纯粹是为了将其与预增量运算符 operator++() 区分开来。此外,您需要重载 operator*() 来取消引用迭代器。

【讨论】:

    【解决方案3】:

    *(b+1) 之所以有效,是因为你会做数学。数学将括号考虑在内。只有在完成数学运算后,才会计算表达式。

    *(++b) 有效,因为您在评估之前递增(前缀递增)。

    *(b++) 不起作用,因为您在评估后递增(后缀递增)。

    【讨论】:

      猜你喜欢
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 2013-10-20
      相关资源
      最近更新 更多