Ulrich Diez <ulrich.diez@alumni.uni-tuebingen.de.invalid> wrote:
> program Test;
> {$R+}
> {$Q+}
> var
> A: Byte;
> begin
> A := 255;
> WriteLn(A + 3);
> end.
>
>
> Hello!
>
> In the program above, A is of Byte-type. Byte-range is 0..255.
> The result of the addition (258) is out of that range.
> When compiling and running with FreePascal, the program above
> writes "258" to the screen.
> If the addition had taken place in Byte-terms, one would have
> expected some overflow-error instead.
> The addition seems not to be performed in terms of Byte but some
> Integer-type of larger range.
>
> Is this correct? If so: Why?
> Is this choosing of appropriate-sized Integer-types common to
> all Pascal-compilers or is it a FreePascal-specific feature?
>
In Pascal integers are supposed to be mathematical integers. Since
general mathematical integers would require infinite precision, Wirth
made a compromise to make Pascal more practial: he declared that each
program that uses too big values is invalid. Then the compiler can
use machine integers and generate efficient code while programmer
thinks in terms of mathematical integers (of course, programmer
has to avoid overflows, which somewhat spoils the picture). If
the problem dictates that only integers in some small range will
appear programer can declare a subrange type. Such declaration
permits the compiler to allocate only part of machine word to
an integer (also the compiler may insert extra checks verifing
if the value stays in range, but typically the checks are
optional). Still such values are just integers: to perform
(say) an addition the compiler extends them to full words and
then adds full words. So the example above is typical
to Pascal compilers.
Remark: Free Pascal tries to be compatible with Borland Pascal (and
now Borland Delphi) and Borland Pascal in many aspects is quite
different than traditional Pascal compilers (for example the
Byte type _is_ an extension, traditional Pascal used subranges
intead). And if you look at subtle details of addition than
you will note that the type of result depends in a strange way
on arguments (and rules used by Borland Pascal are different
than rules used by Free Pascal). However, at basic level Free
Pascal behaves just like other Pascals.
> Are there compilers where you would have to write e.g.
>
> WriteLn(Integer(A) + 3);
>
> in order to force the addition to be performed without overflow-
> error?
>
As I wrote above, typical Pascal compilers extend arguments to
full machine word. Also typically integer fits into a machine
word, so the the cast above will change nothing. However, some
Pascals (including Free Pascal and Gnu Pascal) allow you to use
integer types bigger than machine word. Now, if arguments are
bigger than machine word addition must be done with extra (double)
precision. But if arguments fits in machine word then addition
is done with single precision. So, it is possible that addition
which overflows in single precison can be done exactly in double
precision. For example using GPC on 32-bit machines in the fragment:
var a : integer;
begin
a := 2147483646;
writeln(a + 3);
writeln(LongInt(a) + 3);
end
the first writeln prints wrong result (-2147483647) and the second
gives correct result (2147483649). Probably similar example can
be constructed for Free Pascal (however Integer and LongInt have
different sizes in FPC and GPC, so the above does not "work" in FPC).
--
Waldek Hebisch
hebisch@math.uni.wroc.pl