Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are the members in the statement with AND operator always checked in the given order?

I would like to know if the following code may ever fail with the access violation or if it's safe. Is the first member of the statement with AND operator always checked as first or may be (by some compiler optimization or something) checked the second one as first ?

var
  Item: TSomething;

procedure DoSomething;
begin
  if Assigned(Item) and (Item.SomeProperty) then
    DoSomethingElse;
end;

Is the code above definitely safe ?

Thanks!

like image 213
Martin Reiner Avatar asked Mar 15 '12 10:03

Martin Reiner


People also ask

How do you use and operator?

The logical AND operator ( && ) returns true if both operands are true and returns false otherwise. The operands are implicitly converted to type bool before evaluation, and the result is of type bool .

What is order of evaluation in C?

Order of evaluation refers to the operator precedence and associativity rules according to which mathematical expressions are evaluated.

Which logical operators perform short-circuit evaluation?

The Boolean AND and OR operators perform short-circuit evaluation, that is, they evaluate the expression on the right of the operator only when it is necessary to determine the overall result of the expression.

What is short-circuit evaluation in C#?

Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression. The compiler stops evaluating the further sub-expressions as soon as the value of the expression is determined.


Video Answer


2 Answers

The code is safe given boolean short-circuit evaluation is active:

In the {$B-} state, the compiler generates code for short-circuit Boolean expression evaluation, which means that evaluation stops as soon as the result of the entire expression becomes evident in left to right order of evaluation.

It is a bit confusing as the B (or BOOLEVAL with long name) directive must be turned OFF to switch short-circuit evaluation ON...

See also Operator Precedence.

like image 120
ain Avatar answered Oct 13 '22 00:10

ain


It depends on your Item.SomeProperty type. If it is Variant, or if there is a variant to be evaluated before it, it will be evaluated and cause AV.

Edit : Forget to mention the workaround : If the SomeProperty is Variant type, you can use

  if Assigned(Item) and StrToBool(Item.SomeProperty) then

It do spend some time to convert the variable to String then back to boolean but at lease it can satisfy all cases of being true / false / non-existence.

Below is a test case for you to see :

unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Generics.Collections;

type
  TTestObj = class
  public
    V : Variant;
    I : Integer;
  end;

  TForm4 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    TOV : TTestObj;
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.btn1Click(Sender: TObject);
begin
  if Assigned(TOV) and (TOV.I = 10) then
    ShowMessage('You will never see this though no AV!');
end;

procedure TForm4.btn2Click(Sender: TObject);
begin
  if Assigned(TOV) and StrToBool(TOV.V) then
    ShowMessage('You will not see AV with StrToBool!');
  if Assigned(TOV) and TOV.V then
    ShowMessage('You will never see this but AVed!');
end;

procedure TForm4.btn3Click(Sender: TObject);
var
  V : Variant;
begin
  V := False;
  if Assigned(TOV) and V and (TOV.I = 10) then
    ShowMessage('You will see AV!');
end;

end.
like image 41
Justmade Avatar answered Oct 12 '22 23:10

Justmade