delphirange-checking

Why doesn't "i := i + 1" give a range-check error for Integers and larger types?


Consider:

{$R+}
i:= 1;
While i > 0 do
  i:= i + 1;
ShowMessage(IntToStr(i));

If I declare i as Byte, Word, Shortint or TinyInt I get a range-check error, as expected. If I declare i as LongWord, Cardinal, Integer, LongInt or Int64 it just goes through the while loop and gets to show the negative or 0 value, which i gets when you pass the upper bound.

Does Delphi 7 not support range checking for 32-bit and 64-bit numbers?


Solution

  • The operation i + 1 doesn't actually produce a range check error. The assignment operation does.

    Delphi evaluates the constant '1' as an Integer and so the right hand side will produce a result that is either an Int64 or an Integer (The larger of i's type and Integer).

    If we expand the line out we get the following

    temp := i + 1 
    i := temp
    

    temp will either be 32 or 64 bits, and will overflow if it hits the upper bound. By the time we do the assignment, we have a perfectly valid 32 or 64bit value so there's no possibility of a range check failure if i is 32bits or more.

    If i is less than 32 bits, it will raise a range check if temp is too large to fit.

    For i >= 32bits, you can catch the overflow error like so:

    {$R+,Q+}
    ...