17

私が行っている最近の契約作業のためにDelphiを選択する必要がありました。誰かに明確にしてもらいたいことのひとつは、などの条件ステートメントでのロジックの実行ですif

私はC/C ++とそれらの言語のバックグラウンドを持っており、ifステートメントが失敗することがわかるとすぐに、残りのロジックは実行されません。例えば:

if (somefunc() == FALSE && anotherfunc() == TRUE)

上記の場合、somefunc()returnsのTRUE場合anotherfunc()は呼び出されません。

私がこれまでに見ることができるものからのDelphiでは、これは当てはまりません。むしろ、

if (somefunc() = False and anotherfunc() = True) then

次に、何somefunc()が返されるかに関係なく、anotherfunc()が呼び出されます。

私はさまざまなDelphiの本を読み、条件付きの章のいくつかを読み直しましたが、この動作についての言及はどこにも見つかりません。誰かが私にこの振る舞いが述べられているDelphiまたはPascalのどこかを指摘できますか?

4

3 に答える 3

24

ドキュメントのリンクはここにあります

ブール短絡評価

 
タイプスイッチ
構文{$B+}または{$B-}{$BOOLEVALON}または{$BOOLEVALOFF}
デフォルト{$B-}{$ BOOLEVAL OFF}
スコープローカル

$ Bディレクティブは、 andおよびorブール演算子のDelphiコード生成の2つの異なるモデルを切り替えます。

{$ B +}状態では、コンパイラは完全なブール式評価のためのコードを生成します。これは、式全体の結果がすでにわかっている場合でも、andおよびor演算子から構築されたブール式のすべてのオペランドが評価されることが保証されていることを意味します。

{$ B-}状態では、コンパイラはブール式の短絡評価用のコードを生成します。これは、式全体の結果が評価の左から右の順序で明らかになるとすぐに評価が停止することを意味します。

ご覧のとおり、デフォルトのオプションは短絡評価用です。


残念ながら、テストで少し混乱しました。実際、DelphiコードはCコードとはかなり異なります。

if (somefunc() == FALSE && anotherfunc() == TRUE)      // C code
if (somefunc() = False and anotherfunc() = True) then   // Delphi code

Delphiでは、and演算子は等式演算子よりも優先順位が高くなり=ます。これは、Delphiコードが次のものと同等であることを意味します。

if (somefunc() = (True and anotherfunc()) = True) then

ただし、CおよびC ++では、優先順位は逆です。したがって、。よりも優先順位&&低く==なります。したがって、短絡評価に関係なく、質問のDelphiとC++のifステートメントは論理的に異なります。

私はあなたが本当に次のようにDelphiコードを書くつもりだったと確信しています:

if ((somefunc() = False) and (anotherfunc() = True)) then 

これにより、C ++コードと同じロジックが得られ、短絡評価のために同じ動作が見られます。

最後に、Delphiに対してテストしFalseたりTrue、Delphiでテストしたりしないでください。常に次のようなコードを記述してください。

if not somefunc() and anotherfunc() then 
于 2013-02-26T10:11:15.563 に答える
5

このコードで関数anotherfunc()が呼び出された場合

if (somefunc() = False and anotherfunc() = True) then

次に、を設定しましたBOOLEVAL ON

Davidが指摘したように、コンパイラは最初に評価しますFalse and anotherfunc()

BOOLEVAL OFFモードでは、コンパイラーはそれをFalse and AnyBoolState認識しているため、呼び出されないFalseため、anotherfunc()呼び出されません(実際には呼び出されません)。

その簡単なテストとして、私はあなたの表現を示すためにjachaguateプログラムを拡張しました

program AndEvaluation;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

function FalseFunc( const AName : string ) : Boolean;
begin
  Write( AName, '(False)', '-' );
  Result := False;
end;

function TrueFunc( const AName : string ) : Boolean;
begin
  Write( AName, '(True)', '-' );
  Result := True;
end;

begin
  try

    // (somefunc() = False and anotherfunc() = True)
    //
    // in this testcase translated to:
    //
    // somefunc()    => FalseFunc( 'First' )
    // False         => FalseFunc( 'Second' )
    // anotherfunc() => TrueFunc( 'Third' )
    // True          => TrueFunc( 'Fourth' )

{$B+}
    Writeln( 'BOOLEVAL ON' );
    if ( FalseFunc( 'First' ) = FalseFunc( 'Second' ) and TrueFunc( 'Third' ) = TrueFunc( 'Fourth' ) )
    then
      Writeln( 'True' )
    else
      Writeln( 'False' );
{$B-}
    Writeln( 'BOOLEVAL OFF' );
    if ( FalseFunc( 'First' ) = FalseFunc( 'Second' ) and TrueFunc( 'Third' ) = TrueFunc( 'Fourth' ) )
    then
      Writeln( 'True' )
    else
      Writeln( 'False' );

  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

  ReadLn;

end.

そして今、結果を見てみましょう

BOOLEVAL ON
Second(False)-Third(True)-First(False)-Fourth(True)-True

BOOLEVAL OFF
First(False)-Second(False)-Fourth(True)-True

出力が説明しているようにBOOLEVAL ON、あなたanotherfunc() somefunc()に呼び出されることは呼び出されます。

あなたBOOLEVAL OFFanotherfunc()決して呼ばれません。

あなたがと同じにしたい場合

if (somefunc() == FALSE && anotherfunc() == FALSE)

あなたはそれをこのように翻訳しなければなりません

if ( somefunc() = False ) and ( anotherfunc() = False ) then

またはより良い、より短い方法

if not somefunc() and not anotherfunc() then

または多分さらに短い

if not( somefunc() or anotherfunc() ) then

anotherfunc()ただし、設定する必要があるたびに呼び出されるのを避けるためBOOLEVAL OFF

于 2013-02-26T16:03:11.097 に答える
0

関数を呼び出さないようにするには、次のようにします。

  bool_somefunc := (somefunc() = 42);
  bool_anotherfunc := (anotherfunc() = 17);
  if ( (bool_somefunc = False) and (bool_anotherfunc = True) ) then

これにより、すべての関数が呼び出され、shortevalがオンまたはオフになります。

于 2017-04-09T00:29:50.097 に答える