无法预测的布尔比较c++

Unpredictable boolean comparison c++

本文关键字:c++ 比较 布尔 无法预测      更新时间:2023-10-16

为什么这个代码会产生看似随机的行为,

std::cout << ( thePointerIsGood = ( NULL != (aPointer = aFunctionThatReturnsAPointer(args)) ) );

什么时候这个多行版本可以做同样的事情?

aPointer = aFunctionThatReturnsAPointer(args);
thePointerIsGood = (NULL != aPointer);
std::cout << thePointerIsGood;

我正在捕获aPointerthePointerIsGood,因为我稍后会在代码中使用它们。

更新

事实上,上面的方法很好。但我能够用这个程序重现一些奇怪的行为,我已经标记了错误发生的地方:

// Compiled with:
//   gcc test.cpp -c -o test.o; gcc -lstdc++ test.o -o test
#include <iostream>
#include <cstdlib>
  class
AClass
  { public
    : // Operators ///////////////////////////////////////
      ;  const  bool  operator==  (  const  int  rhs  )  ;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  }
  ;
  class
AHelperClass
  { public
    : // Functions //////////////////////////////////////////////////////
      ;  static  AClass*  AFunctionThatReturnsAPointer  (  int  arg  )  ;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  }
  ;
  const
  bool
  AClass::
operator==
  (  const  int  rhs  )
  { return (rhs == 222); }
  AClass*
  AHelperClass::
AFunctionThatReturnsAPointer
  (  int  arg  )
  { return ( (arg == 777)
           ? new AClass
           : NULL
           )
           ;
  }
  int
main
  (     int  argc
  ,  char**  argv
  )
  { // Variables //////////////////
    ;  AClass*  aPointer          ;
    ;     bool  thePointerIsGood  ;
    ;     bool  theValueMatches   ;
    ;      int  i                 ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    for ( i = 0
        ; i < 10
        ; i++
        )
        { // First a good pointer
          std::cout << ( ( thePointerIsGood = ( NULL != ( aPointer = AHelperClass::AFunctionThatReturnsAPointer(777) ) ) )
                       ? "Y  "
                       : "N  "
                       )  
                    << ( (thePointerIsGood == true)
                       ? "expected    "
                       : "unexpected  " 
                       )
                    ;
          if ( !thePointerIsGood )
             { std::cout << std::endl; }
          else
             { // This is where the error is, thanks to Peter for pointing it out
               std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;
             }

          delete aPointer;
          // Now a NULL pointer
          std::cout << ( ( thePointerIsGood = ( NULL != ( aPointer = AHelperClass::AFunctionThatReturnsAPointer(877) ) ) )
                       ? "Y  "
                       : "N  "
                       )  
                    << ( (thePointerIsGood == false)
                       ? "expected    "
                       : "unexpected  " 
                       )
                    ;
          if ( !thePointerIsGood )
             { std::cout << std::endl; }
          else
             { std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;
             }

          delete aPointer;
        }
    return 0;
  }

它为我产生了以下输出(一切都应该说是预期的)

Y  expected    Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  

我认为以下是未定义的行为:

std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;

因为theValueMatches在同一表达式中被使用和赋值,并且没有定义赋值是在与true比较之前还是之后。如果它看起来是不确定的,我会感到惊讶,因为你会期望编译器选择一种或另一种方法,尽管我观察到我的方法不是——我每次都从程序中得到相同的输出,其中有很多意想不到的东西。

表达式的求值顺序没有保证。如果您有:

x << (a = b) << a;

然后"a"可以在"(a=b)"之前进行评估