【问题标题】:Post-Decrement operator [duplicate]后减运算符 [重复]
【发布时间】:2016-02-02 04:03:16
【问题描述】:

请告诉我 x 之后的值是什么(用 c 语言)

x=1;

x=x--&&++x;

我认为它应该是 0,因为x&&++x 会给出 1,而后减量会使其成为 0。

但是当我在计算机上输入这个结果是 1。 为什么后减量在这里不起作用。

我是这样想的:

pre 递增的优先级高于 && 所以两个 x 都应该被视为 2(布尔值 true )所以 x&&++x 将给出 1 而后递减应该将其递减为 0。

这不是一个重复的问题,因为这不是关于后减量如何工作的未定义行为的情况。

【问题讨论】:

  • 命名你编程的语言?
  • 如果这是关于 C 的,那么表达式会产生未定义的行为,x 允许编译器让恶魔飞出你的鼻子。如果是关于 C 的,那么这个问题已经在这里被问了太多次了。
  • 为了避免未定义的行为,你需要写int y = x--&&++x; x=y;
  • @oo_miguel:如果您的some_expression_with_x 修改了x 的值,就会出现问题。短路评估是一个红鲱鱼,在这里。 x = something 修改了xx-- 也是如此,所以x = x-- 在同一表达式中修改了两次x 的值,修改之间没有序列点。

标签: c decrement


【解决方案1】:
x=x--&&++x;

这会导致 未定义的行为,因为 x 的值在两个序列点之间发生了多次更改。

表达式 x-- && ++x 定义良好,因为 && 具有内部序列点,但是当您将其分配给 x 时,它会导致未定义的行为。

因此,表达式表现出未定义的行为。

C99 §6.5:“2.在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。”

【讨论】:

  • 我试过很多次,很多编译器的结果总是1。
  • 如果它解释了双重修改发生的位置,这将是一个更好的答案。因为在&& 的左右两侧之间有一个序列点,而不是在++xx 的分配之间。
  • @DhruvaMehrotra 这并不意味着编译器上的正确或相似答案意味着它是一个定义明确的行为。也可能是在未定义行为的情况下。
  • @PaulHankin 我认为这就足够了,但谢谢我在回答中提到了它:-)
【解决方案2】:

虽然(x--)&&(++x); 的结果定义明确,但由于short circuit evaluation

你的作业结果 x = (x--)&&(++x);不是

一个更简单的例子是:

x = x--;

正如 Paul 和 Art 在 cmets 中指出的那样:

在同一个表达式中修改 x 的值两次,不带 a 修改之间的序列点。


编辑: 修复了我最初的错误答案,该答案指出分配的结果已定义。

【讨论】:

  • 如果 x=1;和 x-- 返回 1 怎么样?
  • 哈哈,是的。我最初的想法是一样的,但是后来我注意到它实际上是 not undefined :)
  • 你怎么认为它不是未定义的。对我来说,它看起来未定义。 ++xx = 1 之间没有序列点。
  • @DarkDust x--++x 之间有一个序列点,但++xx = 1 之间没有序列点。
  • @oo_miguel x = x++ 是未定义行为的教科书示例。请参阅此问题的最高投票答案,它引用了标准的相关部分。一个对象在序列点之间不能被多次修改。在这个表达式中,同一对象有一个序列点和三个修改。为什么是另一回事。它与优化以及我们允许编译器逃避的事情有关。序列点的规则足够宽松,可以让编译器逍遥法外,但也足够奇怪,即使是经验丰富的 C 程序员也会感到困惑。
【解决方案3】:

尽管我的大学有考试,但我无法停止思考这个问题,我想我终于找到了解决方案。

首先,后减运算符将在 && 的左侧执行,它将 x 的值减为 0,但 x-- 将为 1(x 的先前值),因为左侧为 1 右侧将在这里执行 ++x 将为 x 赋值 1 并且 ++x 的值也将为 1 因此 && 运算符将返回值 1. 现在,虽然在预增量运算符和赋值运算符之间没有序列点,但两者都在赋值1 到 x 所以这完全定义了在整个代码执行后 x 的值为 1。

【讨论】:

  • 如果我仍然错了,请告诉我。
  • 这里的优先级是&&的左侧&&的右侧之前。
  • @DarkDust 我研究了 c 中的优先级图表,它没有说明逻辑和的左侧或右侧
  • 参见 C99 §6.5.13(4):“与按位二进制 & 运算符不同,&& 运算符保证从左到右求值;在求值之后有一个序列点第一个操作数。如果第一个操作数比较等于 0,则不计算第二个操作数。" 这里的关键点是有一个序列点:因此计算左侧,解决所有副作用,并且仅然后是评估右侧。
  • @DarkDust :现在看看我已经证明这不是未定义的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-18
  • 2014-06-12
  • 1970-01-01
  • 2012-04-13
  • 2020-01-14
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多