Node:Type Casts, Next:OOP, Previous:String Slice Access, Up:Programming

### Type Casts

In some cases, especially in low-level situations, Pascal's strong typing can be an obstacle. To temporarily circumvent this, GPC defines explicit "type casts" in a Borland Pascal compatible way.

There are two kinds of type casts, value type casts and variable type casts.

Value type casts

To convert a value of one data type into another type, you can use the target type like the name of a function that is called. The value to be converted can be a variable or an expression. Both the value's type and the destination type must be ordinal or pointer types. The ordinal value (extended to pointers to mean the address) is preserved in the cast.

An example:

    program TypeCastDemo;

    var
      Ch: Char;
      i: Integer;

    begin
      i := Integer (Ch)
    end.

Another, more complicated, example:

    program TypeCst2Demo;

    type
      CharPtr = ^Char;
      CharArray = array [0 .. 99] of Char;
      CharArrayPtr = ^CharArray;

    var
      Foo1, Foo2: CharPtr;
      Bar: CharArrayPtr;

    {$X+} { We need extended syntax in order to use ``Succ'' on a pointer }

    begin
      Foo1 := CharPtr (Bar);
      Foo2 := CharPtr (Succ (Bar))
    end.

However, because of risks involved with type casts, explained below, and because type-casts are non-standard, you should try to avoid type casts whenever possible - and it should be possible in most cases. For instance, the first example above could use the built-in function "Ord" instead of the type cast:

    i := Ord (Ch);

The assignments in the second example could be written in the following way without any type casts:

    Foo1 := @Bar^[0];
    Foo2 := @Bar^[1];

Note: In the case of pointers, a warning is issued if the dereferenced target type requires a bigger alignment than the dereferenced source type (see Alignment).

Variable type casts

It is also possible to temporarily change the type of a variable (more generally, any "lvalue", i.e. something whose address can be taken), without converting its contents in any way. This is called variable type casting.

The syntax is the same as for value type casting. The type-casted variable is still the same variable (memory location) as the original one, just with a different type. Outside of the type cast, the variable keeps its original type.

There are some important differences between value and variable type casting:

- Variable type casting only works on lvalues, not on expressions.
- The result of a variable type casting is still an lvalue, so it can be used, e.g., on the left side of an assignment, or as the operand of an address operator, or passed by reference to a procedure.
- No values are converted in variable type-casting. The contents of the variable, seen as a raw bit pattern, are just interpreted according to the new type.
- Because bit patterns are just interpreted differently, the source and target type must have the same size. If this is not the case, GPC will give a warning.
- Beware: Variable type casts might have unexpected effects on different platforms since you cannot rely on a specific way the data is stored (e.g. see Endianness).

There are cases where a type-cast could be either a value or a variable cast. This is when both types are ordinal or pointer, and of the same size, and the value is an lvalue. Fortunately, in those cases, the results of both forms are the same, since the same ordinal values (or pointer addresses) are represented by the same bit patterns (when of the same size). Therefore, it doesn't matter which form of type-casting is actually used in these cases.

When dealing with objects (see OOP), it is sometimes necessary to cast a polymorphic pointer to an object into a pointer to a more specialized (derived) object (after checking the actual type). However, the `as` operator is a safer approach, so type-casts should be used there only for backward-compatibility (e.g., to BP).

See also: absolute, Alignment, Endianness, OOP, Ord, Chr, Round, Trunc.