【问题标题】:How do C++ operators workC++ 运算符的工作原理
【发布时间】:2011-04-18 02:07:04
【问题描述】:

假设 x = 2、y = 1 和 z = 0,以下语句将显示什么?

printf("answer = %d\n", (x || !y && z));

这是在一个测验中,我弄错了,我不记得我的教授讲过这个,请高人赐教...我知道我得到的答案是 1,但是为什么呢?

【问题讨论】:

标签: c++ operators operator-precedence


【解决方案1】:

表达式被解释为x || (!y &&z)(查看运算符||!&&的优先级。

||short-circuiting 运算符。如果左侧操作数为真(在|| 的情况下),则无需计算右侧操作数。

在您的情况下,x 为真,因此作为布尔表达式,结果将为 1。

编辑

&&||的求值顺序保证从左到右。

【讨论】:

  • 您介意解释“短路”吗?
  • 短路布尔求值意味着如果左侧值足以确定整个表达式的真实性,则根本不评估右侧值。这既是一种优化,也是在检查左侧的指针不为空,然后在右侧取消引用它时必不可少的。对于 || - OR 运算符 - 如果左侧值为真,则整个表达式为真,右侧部分不求值。
  • @Tony:右手部分是否被 评估 无关紧要,因为它没有副作用。重要的是&&|| 具有更高的优先级(即绑定更紧密)。
  • 哦,好吧,有道理,谢谢!
  • @R:是的,你是对的,为了更清楚,我已经编辑了我的答案。
【解决方案2】:

如果我没记错的话,它会打印 1。(假设短路已关闭)

(x || !y && z)(true || !true && false) 将首先评估 !运营商给(true || false && false)

然后是 &&:(true || false)

然后|| :true

Printf 会将十进制的 true 解释为 1。因此它将打印 answer = 1\n

【讨论】:

  • 该!不会先评价! x 将是。
  • 错误 - 请参阅 Prasoon 的回答并考虑短路评估。
  • 注意我说假设没有短路。但否则你是对的。我想他可能想要一个更彻底的答案。
  • 如果您的编译器允许禁用短路,请删除它。
  • @jweyrich:确实我会删除它。我的目的是向正在学习的学生说明操作的顺序。
【解决方案3】:

假设 x = 2、y = 1 和 z = 0, 以下陈述将是什么 显示?

printf("answer = %d\n", (x || !y && z));

好的 - 对这个问题的严厉讽刺和糟糕的措辞感到有点内疚,所以我会尝试以与其他答案不同的方式来帮助你...... :-)

当您遇到这样的问题时,将其分解为易于管理的块。

试试:

int x = 2, y = 1, z = 0;

printf("true == %d\n", 10 > 2);                 // prints "1"
printf("false == %d\n", 1 == 2);                // prints "0"
printf("!y == %d\n", !y);                       // prints "0"
printf("(x || !y) == %d\n", x || !y);           // "1" - SEE COMMENTS BELOW
printf("(!y || z) == %d\n", !y || z);           // "0"
printf("(x || !y && z) == %d\n", x || !y && z); // "1"

在那里的输出中,您已经获得了推断正在发生的一切所需的一切:

  • true == 1 揭示了 C/C++ 如何将真实的布尔表达式转换为 printf 的整数值 1,而不管布尔表达式中出现的值是什么
  • false == 0 揭示了 C/C++ 如何将错误表达式转换为“0”
  • (!y) == 0 因为!是逻辑非运算符,C/C++认为0是唯一对应false的整数值,其他都是true,所以!1 == !true == false == 0
  • (x || !y) == 1,你知道 !y 是 0,所以替换已知值并简化:(2 || 0) == 1 等价于 (true or false) == true...这是可以理解的逻辑规则
  • (!y || z) == 0 - 替换已知值:(0 || 0) == (false or false) == false == 0
  • (x || !y && z) == 1: 紧要关头来了!从上面我们知道:
    • x || !y 是 1/true,如果相关则意味着 1/true && z/0/false == 1/true
    • (!y && z) 为假,如果相关则意味着 x/2/true || false == 1/true

通过这种方式,我们推导出了运算符的优先级——|| 的求值顺序。和 && 运算符,从编译器显示的结果中可以看出,当且仅当 && 在 || 之前被评估然后我们可以对结果有所了解。

【讨论】:

    【解决方案4】:
    answer = 1
    

    或者也许:

    answer = -27
    2 || !1 && 0
    2 || 0 && 0
    2 || 0
    true
    true = non-zero value
    printf("answer = %d",*true*); -> who knows
    

    大多数编译器将输出answer = 1。我不会自信地说所有编译器都会这样做,但我相信所有编译器都会返回非零值。

    【讨论】:

    • 错了,短路无关紧要。这只是副作用是否发生的问题。这是一个简单的运算符优先级问题。如果您不相信我,请尝试将&& 替换为,(逗号运算符)。 :-)
    • 不,答案始终为 1。逻辑 AND 和 OR 的结果始终是 int,其值为 01。 C++ 是一样的,只是类型是bool,当传递给printf 时,它会被提升为int
    • 现在你错了一个新的原因。答案始终是 1。C 中逻辑运算符的结果明确定义为 0 或 1;这不是实施问题。
    • @R.:问题标记为 C 和 C++
    • @RC 历史悠久。比 C 标准要长得多。第一个 C 编译器出现在 70 年代中期,而第一个 C 标准大约是 89 年。当使用一种实现远远早于标准的语言时,它总是一个实现问题。真正的 非零关系在 C 中很猖獗。随意去测试每个编写过的 C 编译器,并证明它们都不是这样工作的——除此之外——没有销售。但是,我将更新我的帖子以更改“C 兼容”以指示编译器可能返回。
    【解决方案5】:

    我不会给你直接的答案,因为你可以编译并运行它,但问题只是测试你是否知道运算符优先级。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 2015-09-27
      • 1970-01-01
      • 2013-09-26
      相关资源
      最近更新 更多