关于评价顺序与比较的几个问题 在C/C++面试中,我发现了一些我没有正确回答的问题,我用Visual C++来检查结果,希望你能帮助我理解:

关于评价顺序与比较的几个问题 在C/C++面试中,我发现了一些我没有正确回答的问题,我用Visual C++来检查结果,希望你能帮助我理解:,c++,boolean-expression,C++,Boolean Expression,(一) 当我在5.2中添加一个float cast时,它可以工作 (三) =>我认为我们总是返回0,因为我认为编译器会将“return x++”转换为:return x;x++;那么我们将永远不会执行增量…下次,当您有多个问题时,请分别提问 对问题1的回答: 有几件事: &&和|运算符都强制从左向右求值1,并且都引入了序列点;在计算右侧操作数之前,将计算左侧操作数并应用所有副作用 &&和|运算符都短路-如果表达式的值可以从左侧操作数确定,则不会计算右侧操作数 在表达式a | | b中,如果a为

(一)

当我在5.2中添加一个float cast时,它可以工作

(三)


=>我认为我们总是返回0,因为我认为编译器会将“return x++”转换为:return x;x++;那么我们将永远不会执行增量…

下次,当您有多个问题时,请分别提问

对问题1的回答:

有几件事:

  • &&
    |
    运算符都强制从左向右求值1,并且都引入了序列点;在计算右侧操作数之前,将计算左侧操作数并应用所有副作用

  • &&
    |
    运算符都短路-如果表达式的值可以从左侧操作数确定,则不会计算右侧操作数

    • 在表达式
      a | | b
      中,如果
      a
      为非零,则不会计算
      b
    • 在表达式
      a和&b
      中,如果
      a
      为零,则不会计算
      b
  • &
    的优先级高于
    |
    ,因此
    a | | b&&c
    被解析为
    a | |(b&&c)

  • x++
    计算为
    x
    的当前值,作为副作用增加
    x

  • ++x
    计算为当前值
    x
    加1,作为副作用,增加
    x

  • 那么,这个表达式呢

    ++i && ++j || ++k
    
    被解析为

    评估结果如下:

  • 评估
    ++i
    ;结果是
    -2
    不是零,因此:
  • ++j
    进行评估;结果是
    3
    ,因此:
  • -2
    3
    均为非零,因此:
  • ++i&&++j
    计算结果为1,因此:
  • ++k
    根本不计算 对问题2的回答:

    同样,有几个问题:

  • 大多数浮点值无法精确表示;它们存储为近似值(不能将无限多个值拟合为有限个位)

  • 浮点常量表达式
    5.2
    的类型为
    double
    ,而不是
    float
    ;要使其浮动,可以使用
    f
    后缀-
    5.2f

  • float
    double
    具有不同的表示形式(double将更多位用于指数和分数),因此它们将为相同的值存储不同的近似值,这就是为什么
    =
    比较不起作用的原因

  • 因此,您不应该使用
    ==
    来比较浮点值;通常,您将获取两个值之间的差值,并确保其小于某个ε值(请记住,ε值取决于大小)

  • 对问题3的回答:

    您正在返回表达式
    x++
    的结果,但该表达式仍然具有递增
    x
    的副作用(副作用在
    return
    语句结束之前应用)


    1.C中的大多数运算符不强制执行特定的求值顺序-给定像
    a+b*C
    这样的表达式,
    a
    b
    C
    中的每一个都可以按任意顺序求值。必须知道
    b*c
    的结果才能添加到
    a
    的结果中,但这并不意味着
    b
    c
    必须在
    a
    之前进行评估

    C和C++在短路逻辑上工作。< /LI> 考虑以下几点:

    bool myBool = (1 || 0+6*4);
    
    myBool
    将尽快进行评估。在本例中,它将计算为true,因为
    |
    中的左参数为true。它立即停止评估。这同样适用于
    &&
    。这就是为什么在布尔运算符的左侧添加更可能失败的情况是惯用做法

  • 这是错误的,因为二进制不能完美地表示浮点数
  • 在这种情况下,它实际上会计算为true。但是,请考虑下面的例子:

    #include <iostream>
    
    int main() {
       double i = 0.1;
       double total = 0.0;
       for(int j = 0; j < 10000; j++) {
          total+=i;
       }
    
       // total = 0.1*10000 = 1000... right?
    
       std::cout << std::boolalpha << "total == 1000.0 ? " << (total == 1000.0) << std::endl;
    
       return 0;
    }
    
    #包括
    int main(){
    双i=0.1;
    双倍合计=0.0;
    对于(int j=0;j<10000;j++){
    总数+=i;
    }
    //总数=0.1*10000=1000…对吗?
    标准::考特问题1:
    
    &&
    运算符的优先级高于
    |
    ,因此将首先对其求值。这两个术语(
    ++i
    ++j
    )有预增量,所以它们分别增加到2和3,然后它们被加上。在C++中,0是“代码> false <代码>,其他的东西都是<代码>真的<代码>。在这种情况下,这两个术语都是<代码>真< /COD>(即,非零)。,所以
    &
    返回
    true
    。现在是测试
    true | |++k
    的时候了。这里,一个优化开始了:因为
    true | | |任何
    都将始终是
    true
    ,编译器甚至不测试表达式。也就是说,它不执行它。
    k
    不会增加。这就是为什么它是一个非常糟糕的h如果语句执行某些操作,则可以将代码放在内部-您无法确定它是否会运行,具体取决于条件。如果需要运行,请确保它没有放在那里,或者可以将其优化掉

    问题2: 浮点算术是很棘手的——精确地表示一个数字通常是不可能的,而真正使用的数字只是一个非常接近的近似值——足够接近它看起来是可行的,但是如果你仔细检查每一个细节,你会发现数字不是它们看起来的样子
    ++i && ++j || ++k
    
    (++i && ++j) || ++k
    
    bool myBool = (1 || 0+6*4);
    
    #include <iostream>
    
    int main() {
       double i = 0.1;
       double total = 0.0;
       for(int j = 0; j < 10000; j++) {
          total+=i;
       }
    
       // total = 0.1*10000 = 1000... right?
    
       std::cout << std::boolalpha << "total == 1000.0 ? " << (total == 1000.0) << std::endl;
    
       return 0;
    }