【问题标题】:How does compiler read these expressions? Why am I getting these outputs(All variables are initialized as 1)? [duplicate]编译器如何读取这些表达式?为什么我得到这些输出(所有变量都初始化为 1)? [复制]
【发布时间】:2016-11-11 01:28:55
【问题描述】:
int x = 1 , y = 1 , z = 1  ;

现在检查这些代码行:-

cout << (++x || ++y)<<endl;     //Output 1
cout << x <<" " << y;          // now x = 2 and y = 1 . Why 'y' is not incremented ?

再次将值初始化为 1

cout <<(++x && ++y )<<endl;     //Output 1
cout << x <<" " << y;         //now x = 2 and y = 2 . Why 'y' is incremented ?

再次将值初始化为 1

cout << (++x ||++y && ++z )<<endl;  //Output 1
cout << x<<" "<< y<<" "<<z ;       //now x = 2 , y = 1 , z = 1.Why these outputs? 

有人可以解释一下编译器是如何读取这些代码的吗? 我阅读了有关优先顺序的信息,但我无法弄清楚编译器如何处理这些类型的代码。即使是小小的帮助也将不胜感激!

【问题讨论】:

标签: c++ operator-precedence


【解决方案1】:

我不确定当您键入 ||&amp;&amp; 时会发生什么。这些都是逻辑 or/and 运算符。

||&amp;&amp; 的有趣之处在于它们的参数是惰性求值的。这称为短路。换句话说,一旦编译器有足够的信息来确定表达式的最终结果,它就会停止计算参数。

cout << (++x || ++y)<<endl;

++x 被评估为布尔值true。由于|| 的一侧为真就足以使整个表达式为真,因此不会评估++y

cout <<(++x && ++y )<<endl;

++x 仍然为真,因此编译器也会计算 ++y,就好像结果是 false,表达式将是 false

第三个留给你自己解决。

我还要补充一点,这是一个非常强大的功能。没有它,以下表达式将取消引用 null 指针:

if( a!=NULL && a->val>3 )...

这样,如果anull,则不会评估右侧,并且不会取消引用a

【讨论】:

  • 懒惰的评估是完全不同的。
  • 这叫短路求值,不是偷懒。
  • 我已经添加了功能的名称,但请注意,懒惰的评估正是如此。仅当需要参数以确定运算符的最终结果时才对参数进行评估。与短路不同,惰性求值是非 C++ 专家可以理解的。
  • 不。惰性求值:在编程语言理论中,惰性求值或按需调用是一种求值策略,它将表达式的求值延迟到需要它的值时,这不是正在发生的事情。没有延迟。发生的事情是编译器足够聪明,可以知道下一个条件是什么并不重要,并完全跳过它的评估。
  • @NathanOliver,可能跳过评估是惰性评估的核心部分,这正是这里发生的事情。您似乎非常重视编译器优化内容的问题,但它只是实现了惰性求值。毕竟,如果 x 设置为 -1y 将被评估。
【解决方案2】:

这叫做短路。

1) 在您的第一种情况下,由于 x 左侧的值为 1,因此永远不会调用运算符 || 的右侧(因为在任何情况下,|| 的结果都是正确的) - 因此y 永远不会增加。

2) 同样在您的第二个示例中,由于x 是左侧的一个,这对&amp;&amp; 没有任何意义-您仍然需要评估右侧才能看到最终结果;如果右手边为假,则结果为假,否则为真。所以在这种情况下,左侧和右侧都被评估。并且xy的值增加了。

3) 同样在第三种情况下,由于短路,涉及yz 的右侧永远不会执行(因为x 的值为1)-因此值为y 和@ 987654334@ 是 1。

这里还有一些info

【讨论】:

    猜你喜欢
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 2015-05-13
    • 1970-01-01
    • 2019-04-02
    • 2013-05-10
    • 2017-06-24
    相关资源
    最近更新 更多