Beginner

Variables and Types in Pascal

Learn about variables, data types, constants, and type conversions in Pascal with practical Docker-ready examples

Pascal’s type system was one of its most influential contributions to programming language design. Niklaus Wirth designed Pascal with strong, static typing to catch errors at compile time rather than at runtime — a philosophy that directly influenced Ada, Modula-2, and eventually Java and C#. Every variable must be declared with its type before it can be used, and the compiler enforces strict type compatibility.

As a procedural, structured language, Pascal separates declaration from execution. All variables are declared in a var section that appears before the begin block. This explicit declaration style makes programs self-documenting and prevents accidental variable creation from typos — a problem that plagued earlier languages.

In this tutorial, you’ll learn how to declare variables, work with Pascal’s built-in data types, use constants, and perform type conversions.

Basic Variable Declarations

Pascal requires all variables to be declared in a var section before they are used. Each declaration specifies the variable name followed by a colon and the type.

Create a file named variables.pas:

program Variables;

var
    age: Integer;
    height: Real;
    initial: Char;
    name: String;
    isStudent: Boolean;

begin
    { Assign values to variables }
    age := 25;
    height := 5.9;
    initial := 'A';
    name := 'Alice';
    isStudent := True;

    WriteLn('Name: ', name);
    WriteLn('Age: ', age);
    WriteLn('Height: ', height:0:1);
    WriteLn('Initial: ', initial);
    WriteLn('Student: ', isStudent);

    { Multiple variables of the same type }
    WriteLn;
    WriteLn('--- Multiple declarations ---');

    { You can declare multiple vars of the same type on one line }
    { For example: x, y, z: Integer; }
    { Let us demonstrate with our existing variables }
    age := age + 1;
    WriteLn('Next year age: ', age);

    { Pascal uses := for assignment, not = }
    { The = sign is used for comparison }
    if age = 26 then
        WriteLn('Age is now 26');
end.

The := Operator

Pascal uses := for assignment, reserving = for equality comparison. This distinction eliminates the common bug in C-family languages where = is accidentally used instead of ==. Wirth considered this separation between assignment and comparison essential for clear, unambiguous code.

Formatting Output

The :0:1 after height in the WriteLn call is Pascal’s output formatting syntax. For real numbers, value:width:decimals controls the minimum field width and decimal places. Using :0:1 means no minimum width and one decimal place.

Numeric Types and Ranges

Pascal provides a rich set of numeric types with well-defined ranges. Understanding these types is important because the compiler enforces range checking.

Create a file named variables_numeric.pas:

program NumericTypes;

var
    { Integer types }
    small: ShortInt;    { -128 to 127 }
    medium: SmallInt;   { -32768 to 32767 }
    normal: Integer;    { Platform-dependent, typically 32-bit }
    large: Int64;       { -2^63 to 2^63-1 }
    positive: Word;     { 0 to 65535 (unsigned) }
    tiny: Byte;         { 0 to 255 (unsigned) }

    { Floating-point types }
    singlePrec: Single;    { ~7 decimal digits }
    doublePrec: Double;    { ~15 decimal digits }
    realNum: Real;         { Alias, typically maps to Double in FPC }

    { Boolean }
    flag: Boolean;

begin
    WriteLn('=== Integer Types ===');
    small := 127;
    medium := 32767;
    normal := 2147483647;
    large := 9223372036854775807;
    positive := 65535;
    tiny := 255;

    WriteLn('ShortInt max: ', small);
    WriteLn('SmallInt max: ', medium);
    WriteLn('Integer max: ', normal);
    WriteLn('Int64 max: ', large);
    WriteLn('Word max: ', positive);
    WriteLn('Byte max: ', tiny);

    WriteLn;
    WriteLn('=== Floating-Point Types ===');
    singlePrec := 3.14159;
    doublePrec := 3.141592653589793;
    realNum := 2.71828;

    WriteLn('Single: ', singlePrec:0:5);
    WriteLn('Double: ', doublePrec:0:15);
    WriteLn('Real: ', realNum:0:5);

    WriteLn;
    WriteLn('=== Boolean ===');
    flag := True;
    WriteLn('Boolean value: ', flag);
    WriteLn('NOT flag: ', not flag);
    WriteLn('True AND False: ', True and False);
    WriteLn('True OR False: ', True or False);

    WriteLn;
    WriteLn('=== Type Sizes ===');
    WriteLn('SizeOf(ShortInt): ', SizeOf(ShortInt), ' byte');
    WriteLn('SizeOf(Integer): ', SizeOf(Integer), ' bytes');
    WriteLn('SizeOf(Int64): ', SizeOf(Int64), ' bytes');
    WriteLn('SizeOf(Single): ', SizeOf(Single), ' bytes');
    WriteLn('SizeOf(Double): ', SizeOf(Double), ' bytes');
end.

Constants and Typed Constants

Pascal supports two kinds of constants: true constants defined with const and typed constants. Constants make programs more readable and maintainable by giving meaningful names to fixed values.

Create a file named variables_constants.pas:

program Constants;

const
    { True constants - value determined at compile time }
    PI = 3.14159265358979;
    MAX_STUDENTS = 30;
    GREETING = 'Hello';
    TAX_RATE = 0.08;
    IS_DEBUG = False;

    { Typed constants - type is explicitly specified }
    MIN_AGE: Integer = 18;
    APP_NAME: String = 'MyApp';

var
    radius, area, circumference: Real;
    totalWithTax: Real;
    i: Integer;

begin
    WriteLn('=== Using Constants ===');
    WriteLn('Greeting: ', GREETING);
    WriteLn('Max students: ', MAX_STUDENTS);
    WriteLn('Tax rate: ', TAX_RATE:0:2);
    WriteLn('Debug mode: ', IS_DEBUG);

    WriteLn;
    WriteLn('=== Circle Calculations ===');
    radius := 5.0;
    area := PI * radius * radius;
    circumference := 2 * PI * radius;

    WriteLn('Radius: ', radius:0:1);
    WriteLn('Area: ', area:0:2);
    WriteLn('Circumference: ', circumference:0:2);

    WriteLn;
    WriteLn('=== Tax Calculation ===');
    totalWithTax := 100.0 * (1 + TAX_RATE);
    WriteLn('Price: $100.00');
    WriteLn('With tax: $', totalWithTax:0:2);

    WriteLn;
    WriteLn('=== Typed Constants ===');
    WriteLn('Min age: ', MIN_AGE);
    WriteLn('App name: ', APP_NAME);

    WriteLn;
    WriteLn('=== Enumerated and Subrange Types ===');

    { Demonstrating Ord with characters and booleans }
    WriteLn('Ord(''A''): ', Ord('A'));
    WriteLn('Ord(True): ', Ord(True));
    WriteLn('Chr(65): ', Chr(65));
end.

Type Conversions

Pascal’s strong type system means you cannot freely mix types. The compiler requires explicit conversions in many cases, which helps prevent subtle bugs.

Create a file named variables_convert.pas:

program TypeConversions;

var
    intVal: Integer;
    floatVal: Real;
    strVal: String;
    charVal: Char;
    boolVal: Boolean;
    code: Integer;

begin
    WriteLn('=== Numeric Conversions ===');

    { Integer to Real - implicit widening is allowed }
    intVal := 42;
    floatVal := intVal;
    WriteLn('Integer to Real: ', intVal, ' -> ', floatVal:0:1);

    { Real to Integer - must use Trunc or Round }
    floatVal := 3.7;
    WriteLn('Trunc(3.7): ', Trunc(floatVal));
    WriteLn('Round(3.7): ', Round(floatVal));

    floatVal := 3.2;
    WriteLn('Trunc(3.2): ', Trunc(floatVal));
    WriteLn('Round(3.2): ', Round(floatVal));

    WriteLn;
    WriteLn('=== String Conversions ===');

    { Integer to String }
    intVal := 255;
    Str(intVal, strVal);
    WriteLn('Integer to String: ', intVal, ' -> "', strVal, '"');

    { String to Integer }
    strVal := '123';
    Val(strVal, intVal, code);
    if code = 0 then
        WriteLn('String to Integer: "', strVal, '" -> ', intVal)
    else
        WriteLn('Conversion error at position: ', code);

    { Float to String with formatting }
    floatVal := 3.14159;
    Str(floatVal:0:2, strVal);
    WriteLn('Float to String: ', floatVal:0:5, ' -> "', strVal, '"');

    WriteLn;
    WriteLn('=== Character Conversions ===');

    { Char to Integer (ASCII value) }
    charVal := 'Z';
    WriteLn('Ord(''Z''): ', Ord(charVal));

    { Integer to Char }
    intVal := 97;
    charVal := Chr(intVal);
    WriteLn('Chr(97): ', charVal);

    WriteLn;
    WriteLn('=== Boolean Conversions ===');
    boolVal := True;
    WriteLn('Ord(True): ', Ord(boolVal));
    WriteLn('Ord(False): ', Ord(False));

    { Integer to Boolean }
    intVal := 0;
    boolVal := Boolean(intVal);
    WriteLn('Boolean(0): ', boolVal);
    intVal := 1;
    boolVal := Boolean(intVal);
    WriteLn('Boolean(1): ', boolVal);
end.

The Val Procedure

The Val procedure is Pascal’s way of parsing strings into numbers. It takes three parameters: the source string, the destination variable, and an error code. If conversion succeeds, the error code is 0. If it fails, the error code indicates the position in the string where parsing failed. This explicit error handling is typical of Pascal’s safety-first design philosophy.

Running with Docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Pull the Free Pascal image
docker pull freepascal/fpc:latest

# Run the basic variables example
docker run --rm -v $(pwd):/app -w /app freepascal/fpc:latest sh -c 'fpc variables.pas && ./variables'

# Run the numeric types example
docker run --rm -v $(pwd):/app -w /app freepascal/fpc:latest sh -c 'fpc variables_numeric.pas && ./variables_numeric'

# Run the constants example
docker run --rm -v $(pwd):/app -w /app freepascal/fpc:latest sh -c 'fpc variables_constants.pas && ./variables_constants'

# Run the type conversions example
docker run --rm -v $(pwd):/app -w /app freepascal/fpc:latest sh -c 'fpc variables_convert.pas && ./variables_convert'

Expected Output

From variables.pas:

Name: Alice
Age: 25
Height: 5.9
Initial: A
Student: TRUE

--- Multiple declarations ---
Next year age: 26
Age is now 26

From variables_numeric.pas:

=== Integer Types ===
ShortInt max: 127
SmallInt max: 32767
Integer max: 2147483647
Int64 max: 9223372036854775807
Word max: 65535
Byte max: 255

=== Floating-Point Types ===
Single: 3.14159
Double: 3.141592653589793
Real: 2.71828

=== Boolean ===
Boolean value: TRUE
NOT flag: FALSE
True AND False: FALSE
True OR False: TRUE

=== Type Sizes ===
SizeOf(ShortInt): 1 byte
SizeOf(Integer): 4 bytes
SizeOf(Int64): 8 bytes
SizeOf(Single): 4 bytes
SizeOf(Double): 8 bytes

From variables_constants.pas:

=== Using Constants ===
Greeting: Hello
Max students: 30
Tax rate: 0.08
Debug mode: FALSE

=== Circle Calculations ===
Radius: 5.0
Area: 78.54
Circumference: 31.42

=== Tax Calculation ===
Price: $100.00
With tax: $108.00

=== Typed Constants ===
Min age: 18
App name: MyApp

=== Enumerated and Subrange Types ===
Ord('A'): 65
Ord(True): 1
Chr(65): A

From variables_convert.pas:

=== Numeric Conversions ===
Integer to Real: 42 -> 42.0
Trunc(3.7): 3
Round(3.7): 4
Trunc(3.2): 3
Round(3.2): 3

=== String Conversions ===
Integer to String: 255 -> "255"
String to Integer: "123" -> 123
Float to String: 3.14159 -> "3.14"

=== Character Conversions ===
Ord('Z'): 90
Chr(97): a

=== Boolean Conversions ===
Ord(True): 1
Ord(False): 0
Boolean(0): FALSE
Boolean(1): TRUE

Key Concepts

  • Declare before use — All variables must be declared in a var section before the begin block. This prevents accidental variable creation and makes program structure explicit.
  • := for assignment, = for comparison — Pascal deliberately separates these two operations, eliminating an entire class of bugs common in C-family languages.
  • Strong static typing — The compiler enforces type compatibility and catches mismatches at compile time. You cannot assign a String to an Integer without explicit conversion.
  • Rich numeric types — Pascal provides sized integer types (ShortInt, SmallInt, Integer, Int64) and unsigned types (Byte, Word), giving precise control over numeric ranges.
  • Constants with const — Named constants improve readability and maintainability. Pascal supports both untyped constants (type inferred from value) and typed constants (type explicitly declared).
  • Explicit type conversions — Functions like Trunc, Round, Ord, Chr, Str, and Val make conversions visible in the code, so there are no hidden coercions.
  • Output formatting — The value:width:decimals syntax in Write/WriteLn provides built-in output formatting without needing a separate format function.
  • Case insensitivity — Pascal identifiers are case-insensitive, so Integer, INTEGER, and integer all refer to the same type.

Running Today

All examples can be run using Docker:

docker pull freepascal/fpc:latest
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining