Operators in Pascal
A practical tour of arithmetic, relational, logical, bitwise, and set operators in Pascal with runnable Free Pascal examples
Operators are the verbs of Pascal expressions — the symbols and keywords that combine values to produce new ones. Pascal’s operator design reflects its origins as a teaching language: arithmetic is split cleanly between integer and real domains, logical operators use English words rather than cryptic symbols, and even sets get first-class operator support.
If you’re coming from C or Python, three things stand out immediately. First, assignment is :=, not = — the single = is reserved for equality testing. Second, integer division and real division are different operators (div vs /). Third, Pascal’s logical operators (and, or, not, xor) double as bitwise operators when applied to integers, with the compiler choosing the meaning based on operand type.
This tutorial walks through every category of operator in Free Pascal: arithmetic, relational, logical/bitwise, set, string, and assignment. Each section includes a runnable example you can compile with fpc.
Arithmetic Operators
Pascal cleanly separates integer arithmetic from real (floating-point) arithmetic. The / operator always produces a real result, while div and mod only operate on integers.
Create a file named operators_arith.pas:
program OperatorsArith;
var
a, b: Integer;
x, y: Real;
begin
a := 17;
b := 5;
WriteLn('a = ', a, ', b = ', b);
WriteLn('a + b = ', a + b);
WriteLn('a - b = ', a - b);
WriteLn('a * b = ', a * b);
WriteLn('a div b = ', a div b); { integer division }
WriteLn('a mod b = ', a mod b); { remainder }
WriteLn('a / b = ', a / b:0:4); { real division, 4 decimal places }
x := 2.5;
y := 4.0;
WriteLn('x * y = ', x * y:0:2);
WriteLn('-x = ', -x:0:2); { unary minus }
end.
A few details worth noticing: div truncates toward zero (-7 div 2 gives -3, not -4); mod follows the sign of the dividend; and the formatting suffix :0:4 on a real value means “minimum 0 width, 4 decimal places.” Without it, Pascal prints reals in exponential notation by default.
Pascal does not have a built-in power operator like **. For exponentiation, use the Power function from the Math unit (uses Math; then Power(2, 10)).
Relational Operators
Comparison operators return Boolean (True or False). Note that equality is = and inequality is <> — these will trip up anyone arriving from a C-family language.
Create a file named operators_rel.pas:
program OperatorsRel;
var
a, b: Integer;
begin
a := 10;
b := 20;
WriteLn('a = b : ', a = b); { equality }
WriteLn('a <> b : ', a <> b); { inequality }
WriteLn('a < b : ', a < b);
WriteLn('a <= b : ', a <= b);
WriteLn('a > b : ', a > b);
WriteLn('a >= b : ', a >= b);
{ Strings compare lexicographically }
WriteLn('''apple'' < ''banana'' : ', 'apple' < 'banana');
WriteLn('''cat'' = ''cat'' : ', 'cat' = 'cat');
end.
Pascal’s Boolean values print as TRUE and FALSE by default. Strings compare lexicographically character-by-character, using the underlying character codes (typically ASCII / UTF-8 byte order in Free Pascal).
Logical and Bitwise Operators
Pascal uses the same keywords — and, or, not, xor — for both Boolean logic and bitwise operations. The compiler picks the meaning based on whether the operands are Boolean or integer. Integers also get shl (shift left) and shr (shift right).
Create a file named operators_logic.pas:
program OperatorsLogic;
var
p, q: Boolean;
m, n: Integer;
begin
p := True;
q := False;
WriteLn('p and q : ', p and q);
WriteLn('p or q : ', p or q);
WriteLn('not p : ', not p);
WriteLn('p xor q : ', p xor q);
{ Same keywords, integer operands -> bitwise }
m := 12; { binary 1100 }
n := 10; { binary 1010 }
WriteLn('m and n : ', m and n); { 1000 = 8 }
WriteLn('m or n : ', m or n); { 1110 = 14 }
WriteLn('m xor n : ', m xor n); { 0110 = 6 }
WriteLn('m shl 2 : ', m shl 2); { 110000 = 48 }
WriteLn('m shr 1 : ', m shr 1); { 110 = 6 }
end.
By default, Free Pascal evaluates Boolean expressions fully (no short-circuiting). To enable C-style short-circuit evaluation, compile with -Sc or use the {$BOOLEVAL OFF} directive. This matters when one operand has side effects or could trigger a runtime error (such as dereferencing nil).
Set and String Operators
Sets are a distinctive Pascal feature, and they come with their own operators: + (union), - (difference), * (intersection), and in (membership test). Strings are concatenated with +.
Create a file named operators_sets.pas:
program OperatorsSets;
type
DigitSet = set of 0..9;
var
primes, evens, both: DigitSet;
greeting, name, message: string;
begin
primes := [2, 3, 5, 7];
evens := [0, 2, 4, 6, 8];
both := primes * evens; { intersection: just {2} }
Write('primes * evens = [');
if 2 in both then Write('2');
WriteLn(']');
WriteLn('3 in primes : ', 3 in primes);
WriteLn('4 in primes : ', 4 in primes);
{ Set union and difference behave just like arithmetic }
both := primes + evens; { union }
WriteLn('|primes + evens| includes 7? ', 7 in both);
both := evens - primes; { difference }
WriteLn('|evens - primes| includes 2? ', 2 in both);
{ String concatenation with + }
greeting := 'Hello, ';
name := 'Pascal';
message := greeting + name + '!';
WriteLn(message);
end.
The in operator is also useful far beyond sets-of-sets — it makes range checks readable: if ch in ['a'..'z', 'A'..'Z'] then ....
Assignment and Precedence
Assignment uses :=, which visually distinguishes it from the equality comparison =. Free Pascal (in Delphi or extended-syntax mode) also supports compound assignments +=, -=, *=, and /=.
Operator precedence in Pascal is flatter than in C. There are only four levels, from highest to lowest:
not, unary-,@(address-of)- Multiplying:
*,/,div,mod,and,shl,shr - Adding:
+,-,or,xor - Relational:
=,<>,<,>,<=,>=,in
A consequence of this flat scheme is that Boolean expressions involving relational operators almost always need parentheses. a = 1 and b = 2 parses as a = (1 and b) = 2, which is rarely what you want.
Create a file named operators_assign.pas:
program OperatorsAssign;
{$mode objfpc}{$H+}
var
counter: Integer;
a, b: Integer;
begin
counter := 0;
counter := counter + 1;
counter := counter + 1;
counter := counter * 10;
WriteLn('counter = ', counter);
a := 5;
b := 3;
{ Parentheses required around relational sub-expressions }
if (a > 0) and (b > 0) then
WriteLn('both positive');
{ Precedence demo: not binds tightest, then *-level, then +-level, then relational }
WriteLn('1 + 2 * 3 = ', 1 + 2 * 3); { 7 }
WriteLn('(1 + 2) * 3 = ', (1 + 2) * 3); { 9 }
WriteLn('not False or False = ', not False or False); { True }
end.
The {$mode objfpc} directive enables Object Pascal mode; without it, certain modern conveniences (including some compound-assignment behaviors) may not be available.
Running with Docker
Pull the Free Pascal image and compile each example. The image already contains fpc, so you can compile and run in a single shell invocation.
| |
Expected Output
Running operators_arith:
a = 17, b = 5
a + b = 22
a - b = 12
a * b = 85
a div b = 3
a mod b = 2
a / b = 3.4000
x * y = 10.00
-x = -2.50
Running operators_rel:
a = b : FALSE
a <> b : TRUE
a < b : TRUE
a <= b : TRUE
a > b : FALSE
a >= b : FALSE
'apple' < 'banana' : TRUE
'cat' = 'cat' : TRUE
Running operators_logic:
p and q : FALSE
p or q : TRUE
not p : FALSE
p xor q : TRUE
m and n : 8
m or n : 14
m xor n : 6
m shl 2 : 48
m shr 1 : 6
Running operators_sets:
primes * evens = [2]
3 in primes : TRUE
4 in primes : FALSE
|primes + evens| includes 7? TRUE
|evens - primes| includes 2? FALSE
Hello, Pascal!
Running operators_assign:
counter = 20
both positive
1 + 2 * 3 = 7
(1 + 2) * 3 = 9
not False or False = TRUE
Key Concepts
- Assignment is
:=, equality is=— Pascal uses distinct symbols, removing an entire class of C bugs (if (x = 0)accidentally assigning). - Two division operators —
/always returnsReal;divandmodwork only on integers. Pick the one that matches your intent. and,or,not,xorare dual-purpose — Boolean on Boolean operands, bitwise on integer operands. The compiler resolves the meaning by type.- Flat precedence demands parentheses — Relational operators sit at the lowest level, so
(a > 0) and (b > 0)must be parenthesized. - Sets are first-class —
+,-,*, andinoperate onset oftypes, giving you concise membership and combination tests with no library required. - No power operator — Use
Power(base, exp)from theMathunit for exponentiation. - Boolean evaluation is not short-circuit by default — Enable it with
-Scor{$BOOLEVAL OFF}when you need C-style behavior. - Strings concatenate with
+— Familiar and ergonomic in Free Pascal and Delphi; no special operator or function needed.
Running Today
All examples can be run using Docker:
docker pull freepascal/fpc:latest
Comments
Loading comments...
Leave a Comment