Operators, Expressions & Type Conversion

There is no built-in power operator; use Power(Base, Exp) or IntPower from Math (FPC's ** operator is available when the Math unit is used, which overloads it).

7.1 Arithmetic operators

addition / unary plus / string concatenation integer, real, string subtraction / negation integer division (truncates toward zero) remainder (sign follows the dividend)

There is no built-in power operator; use Power(Base, Exp) or IntPower from Math (FPC's ** operator is available when the Math unit is used, which overloads it).

Writeln(7 / 2);      //  3.5000000000000000E+000
Writeln(7 div 2);    //  3
Writeln(-7 div 2);   // -3
Writeln(7 mod 3);    //  1
Writeln(-7 mod 3);   // -1

7.2 Relational operators

=, <>, <, >, <=, >=, and in (set membership). They return Boolean. Strings compare lexicographically by character code.

7.3 Logical and bitwise operators

logical shift right Short-circuit evaluation is on by default ({$B-}): in A and B, B is not evaluated if A is False. This allows safe idioms:

if (P <> nil) and (P^.Value > 0) then ...
if (I <= High(Arr)) and (Arr[I] = Target) then ...

7.4 Precedence — the classic trap

Pascal has only four precedence levels, and and/or bind tighter than comparisons:

@ not unary - unary + * / div mod and shl shr as + - or xor = <> < > <= >= in is

// WRONG: parsed as  X > (0 and X) < 10  -> compile error
// if X > 0 and X < 10 then ...

// RIGHT: parenthesize every comparison
if (X > 0) and (X < 10) then
  Writeln('in range');

7.5 Assignment and compound operators

X := X + 1;     // assignment is ':=', never '='
Inc(X);         // X := X + 1 (fast, works on all ordinals and typed pointers)
Inc(X, 5);
Dec(X, 2);
X += 3;         // C-style operators: FPC with {$COperators on} (-Sc); not in Delphi

7.6 Implicit conversions

Integer → real: automatic (R := 5;).

Smaller integer → larger integer: automatic.

Real → integer: never implicit; use Trunc or Round.

Char ↔ string: a Char can be assigned to a string.

Between unrelated types (Boolean ↔ Integer, enum ↔ Integer): not implicit; use Ord or a cast.

7.7 Conversion routines

real → integer (truncate) real → integer (round half to even) ordinal → integer integer → char integer ↔ string

IntToStr, StrToInt, StrToIntDef, TryStrToInt FloatToStr, FormatFloat, StrToFloat, TryStrToFloat Boolean ↔ string BoolToStr(B, True), StrToBool any number ↔ string (classic) Str(X:W:D, S), Val(S, X, Code) GetEnumName, GetEnumValue date/time ↔ string

DateToStr, FormatDateTime, StrToDate

program Conversions;
{$mode objfpc}{$H+}
uses SysUtils;
var
  N, Code: Integer;
  R: Double;
  S: string;
begin
  N := StrToInt('42');
  R := StrToFloat('3.5');     // uses the locale's decimal separator
  S := IntToStr(N * 2);
  Writeln(S);                               // 84
  Writeln(FormatFloat('0.00', R));          // 3.50
  Writeln(Trunc(2.7), ' ', Round(2.5), ' ', Round(3.5));  // 2 2 4 (banker's rounding)

  Val('12x', N, Code);
  if Code <> 0 then
    Writeln('Invalid number at position ', Code);   // 3

  if not TryStrToInt('abc', N) then
    Writeln('not an integer');
  Writeln(StrToIntDef('oops', -1));         // -1
end.

7.8 Typecasts

Value casts between ordinal types are unchecked — the programmer takes responsibility. For classes, prefer the checked as operator (Chapter 27).

var
  B: Byte;
  C: Char;
  P: Pointer;
  I: NativeInt;
begin
  B := Byte('A');          // value cast: 65
  C := Char(66);           // 'B'
  I := NativeInt(P);       // pointer to integer of the same size
end.