FreeBasic Procedures
Last modified October 18, 2026
A procedure is a named block of statements that can be called from several places.
FreeBasic has two kinds: a Sub performs an action and returns nothing, while a
Function computes and returns a value. This article covers how to declare them,
how parameters are passed, and how overloading and recursion work. The keyword articles
Sub, Function,
and Declare describe each statement in detail.
Declaring procedures
A procedure is declared with Sub or Function. A function also states the
type of the value it returns, while a sub returns nothing. The Declare statement
repeats a procedure's signature so that it can be called before its body appears in the source
file. The example below declares both procedures first, then calls them, and only afterward
defines their bodies.
Declare Function Square(x As Integer) As Integer
Declare Sub PrintSquare(n As Integer)
PrintSquare(4)
PrintSquare(7)
Sub PrintSquare(n As Integer)
Print n; " squared is "; Square(n)
End Sub
Function Square(x As Integer) As Integer
Return x * x
End Function
The Declare lines at the top announce the signatures of Square and
PrintSquare. This lets code call a procedure before its body appears in the file.
PrintSquare calls Square inside its body, and Square is
defined below it. The Return statement in a function supplies its value. Each
Print number is preceded by a space, which is why the output has two spaces before
the squared values.
$ fbc -lang fb procedures_declare.bas $ ./procedures_declare 4 squared is 16 7 squared is 49
Passing parameters by value and by reference
A parameter declared ByVal receives a copy of the argument, so changes inside the
procedure do not affect the caller. A parameter declared ByRef refers to the caller's
variable, so changes are visible after the call. In the fb dialect, numeric
parameters without a qualifier are passed by value, while String and user-defined
type parameters default to by-reference. Writing the qualifier explicitly makes the intent clear.
Sub AddOneByVal(ByVal n As Integer)
n += 1
End Sub
Sub AddOneByRef(ByRef n As Integer)
n += 1
End Sub
Dim value As Integer = 10
AddOneByVal(value)
Print "After ByVal call: "; value
AddOneByRef(value)
Print "After ByRef call: "; value
AddOneByVal increments its own copy of n, so value remains
10. AddOneByRef increments the caller's variable directly, so value
becomes 11. Sub calls use the statement form without Call.
$ fbc -lang fb procedures_byval.bas $ ./procedures_byval After ByVal call: 10 After ByRef call: 11
Recursion
A procedure may call itself. Each call works on its own copy of the local values. A recursive procedure needs a base case that stops the recursion; without one, the calls never end.
Function Factorial(n As Integer) As LongInt
If n <= 1 Then Return 1
Return n * Factorial(n - 1)
End Function
Print "5! = "; Factorial(5)
Print "15! = "; Factorial(15)
Factorial returns 1 when n is 1 or less, which is the base case. Otherwise
it multiplies n by the factorial of n - 1. The function returns
LongInt because 15! is larger than a 32-bit integer can hold on a 32-bit target;
LongInt is 64 bits on every target.
$ fbc -lang fb procedures_recursion.bas $ ./procedures_recursion 5! = 120 15! = 1307674368000
Array parameters
An array parameter is written with empty parentheses, such as values(). The
procedure then accepts any integer array, and the caller passes the array with empty parentheses
too. Use LBound and UBound inside the procedure so it works with any
bounds.
Sub FillArray(values() As Integer, v As Integer)
Dim i As Integer
For i = LBound(values) To UBound(values)
values(i) = v
Next
End Sub
Dim nums(0 To 3) As Integer
FillArray(nums(), 7)
Print "nums(0) = "; nums(0); ", nums(3) = "; nums(3)
FillArray loops from the lower to the upper bound of values and writes
v to each element. Because array parameters are passed by reference, the caller's
nums array is changed. The call FillArray(nums(), 7) passes the array
and the value.
$ fbc -lang fb procedures_array.bas $ ./procedures_array nums(0) = 7, nums(3) = 7
Overloading
Overloading lets several procedures share one name when their parameter lists differ in type or
count. The Overload keyword is written after the name in each declaration. The
definitions do not repeat it. Parameter names must not be reserved words: width is
reserved in FreeBasic because of the Width statement, so the example uses
w and h.
Declare Function Calc Overload (w As Integer, h As Integer) As Integer
Declare Function Calc Overload (s As Integer) As Integer
Function Calc (w As Integer, h As Integer) As Integer
Return w * h
End Function
Function Calc (s As Integer) As Integer
Return s * s
End Function
Print "Rectangle: "; Calc(4, 5)
Print "Square: "; Calc(4)
The two Calc declarations differ in parameter count, so the compiler chooses the
right version from the call. Calc(4, 5) selects the rectangle version and
Calc(4) selects the square version.
$ fbc -lang fb procedures_overload.bas $ ./procedures_overload Rectangle: 20 Square: 16
Source
Author
List all FreeBasic Tutorials.