ZetCode

FreeBasic Basics

Last modified October 18, 2026

In this article we cover the basic programming concepts of FreeBasic. The examples use the default dialect, which is selected with -lang fb. We start with a small console program and then introduce variables, control flow, arrays, and procedures. For installation instructions, see the FreeBasic introduction.

Compiling a program

Save each complete example in its own .bas file. The compiler creates a native executable; compiling and running are separate steps. Commands beginning with $ below are shell commands, not FreeBasic statements. The examples use a Linux shell; on Windows, run the resulting .exe file instead of ./program.

hello.bas
Print "Hello, FreeBasic!"

Print writes to the console and normally ends the line. Executable statements at module level form the program's starting code; we do not need to define a Main function. Newlines normally separate statements. Indentation improves readability but does not define blocks: keywords such as End If and End Function close them explicitly.

$ fbc -lang fb hello.bas
$ ./hello
Hello, FreeBasic!

Identifiers

Identifiers are names given to variables, procedures, types, and other program entities. They consist of letters, digits, and underscores, and they cannot begin with a digit. Identifiers are not case sensitive: userName and USERNAME refer to the same variable.

Some words are reserved by the language. Reserved words such as name, line, data, input, and ptr cannot be used as identifiers.

identifiers.bas
Dim userName As String = "Lucy"
USERNAME = "Mark"
Print userName

The assignment through USERNAME changes the variable declared as userName. Writing Dim USERNAME As String instead would declare the same name twice and produce a duplicate-definition error. Use consistent spelling even though the compiler ignores case.

$ fbc -lang fb identifiers.bas
$ ./identifiers
Mark

Comments

Comments are ignored by the compiler. A single-line comment starts with an apostrophe. A multi-line comment is enclosed in /' and '/.

comments.bas
' This is a single-line comment
Print "Hello" ' trailing comment
/' This is a
   multi-line comment '/
Print "Done"

The apostrophe can begin a whole comment line or follow executable code. The two-line block between /' and '/ is also a comment; only the two Print statements execute.

$ fbc -lang fb comments.bas
$ ./comments
Hello
Done

Variables

A variable stores a value under a name. Variables are declared with the Dim statement, and the data type follows the keyword As. A variable can be initialized when it is declared.

variables.bas
Dim i As Integer = 1
Dim w As Double = 12.5
Dim s As String = "FreeBASIC"
Dim b As Boolean = True
Print "Count: "; i
Print "Price: "; w
Print "Language: "; s
Print "Enabled: "; b

The variables hold an integer, a floating-point number, a string, and a Boolean value. The semicolon in Print joins the values without adding spaces, and a non-negative number is printed with a leading space. A Boolean value prints as true or false.

Integer holds whole numbers and is target-sized: 32 bits on 32-bit targets and 64 bits on 64-bit targets. Long is always 32 bits, and LongInt is 64 bits. Double represents floating-point values, which can have rounding error. String stores text, while Boolean stores a truth value. A variable keeps its declared type when a new value is assigned to it.

$ fbc -lang fb variables.bas
$ ./variables
Count:  1
Price:  12.5
Language: FreeBASIC
Enabled: true

Operators

The operators +, -, and * perform addition, subtraction, and multiplication. The / operator performs floating-point division; \ performs integer division. Mod gives the remainder. Parentheses group expressions explicitly.

operators.bas
Dim a As Integer = 15
Dim b As Integer = 4
Print "Division: "; a / b
Print "Integer division: "; a \ b
Print "Remainder: "; a Mod b

Although both operands are integers, 15 / 4 gives 3.75. Integer division gives 3, and the remainder is 3. Assignment uses =; in a condition, the same symbol tests equality. Inequality is written <>, not !=.

$ fbc -lang fb operators.bas
$ ./operators
Division:  3.75
Integer division:  3
Remainder:  3

Type inference

The Var keyword declares a variable whose type is taken from the initial value. The initializer is required.

inference.bas
Var age = 34
Var fullName = "John Doe"
Print fullName; " is "; age; " years old"

The type of age is Integer and the type of fullName is String, both inferred from the initial values. This is compile-time inference, not dynamic typing. An unsuffixed floating-point literal such as 3.14 infers Double.

$ fbc -lang fb inference.bas
$ ./inference
John Doe is  34 years old

Constants

Constants are declared with the Const keyword. Their value is fixed at compile time and cannot be changed during the execution of the program.

constants.bas
Const PI As Double = 3.14159265
Const MAX_RETRIES = 3
Print PI; MAX_RETRIES

PI has an explicit type; MAX_RETRIES takes its type from the integer initializer. Uppercase constant names are a convention, not a language requirement. Trying to assign a different value to either constant is a compile-time error.

$ fbc -lang fb constants.bas
$ ./constants
 3.14159265 3

User input

The Input statement prints a prompt and reads a value from the keyboard into a variable. The value is converted to the type of the variable.

userinput.bas
Dim userName As String
Input "Enter your name: ", userName
Print "Hello "; userName

The declaration reserves a string variable, and Input stores the entered text in it. The comma after the prompt suppresses the automatic question mark; a semicolon would append ? . The transcript includes the user's typed response. For a complete line containing commas, use Line Input instead. Numeric Input is not a strict validator: non-numeric text can convert to zero, so applications should validate user input separately.

$ fbc -lang fb userinput.bas
$ ./userinput
Enter your name: Robert
Hello Robert

Conditionals

The If statement executes a block of statements depending on a condition. The ElseIf and Else branches are optional.

conditionals.bas
Dim num As Integer = -3
If num > 0 Then
    Print "The number is positive"
ElseIf num = 0 Then
    Print "The number is zero"
Else
    Print "The number is negative"
End If

The first condition tests whether num is greater than zero. If not, ElseIf tests equality with zero; Else handles the remaining negative values. Exactly one branch runs. Change the initial value to 0 or 3 to try the other branches.

$ fbc -lang fb conditionals.bas
$ ./conditionals
The number is negative

Select Case

The Select Case statement chooses a branch by comparing one expression with several possible values.

switch.bas
Dim day As Integer = 3
Select Case day
    Case 1
        Print "Monday"
    Case 2, 3
        Print "Tuesday or Wednesday"
    Case Else
        Print "Other"
End Select

Several values can be listed in one Case separated by commas. FreeBasic does not fall through to the next case: only the first matching branch is executed. Here day is 3, so Case 2, 3 matches. Case Else is the optional fallback when no earlier case matches.

$ fbc -lang fb switch.bas
$ ./switch
Tuesday or Wednesday

For loop

The For statement repeats a block for a range of values. The loop counter is incremented by one unless a Step is given.

forloop.bas
Dim sum As Integer = 0
For i As Integer = 0 To 9
    sum += i
Next
Print sum

The sum of the values 0 to 9 is 45. The loop variable is declared in the For statement and is local to the loop. Both endpoints are included, so there are ten iterations. The statement sum += i means sum = sum + i. Next advances the counter; Step 2 would advance it by two, and a negative step can count downward.

$ fbc -lang fb forloop.bas
$ ./forloop
 45

While loop

The While loop repeats a block as long as the condition is true. The condition is checked before each iteration, so the body may run zero times. The block is terminated with Wend.

whileloop.bas
Dim i As Integer = 0
While i < 5
    Print i
    i += 1
Wend

The counter starts at zero and is printed before it is incremented. Once it reaches five, the condition is false and the loop ends. Omitting i += 1 would make this loop run indefinitely. Use Exit While for an early exit and Continue While to skip the rest of the current iteration.

$ fbc -lang fb whileloop.bas
$ ./whileloop
 0
 1
 2
 3
 4

Arrays

An array stores several values of the same type under one name. The bounds are given in the declaration; UBound returns the upper bound.

arrays.bas
Dim primes(0 To 4) As Integer = {2, 3, 5, 7, 11}
Dim i As Integer
For i = LBound(primes) To UBound(primes)
    Print primes(i);
Next
Print

The trailing semicolon in Print primes(i); keeps the output on one line. The final Print ends the line. The bounds 0 To 4 allocate five elements, not four; an index selects one element with parentheses, as in primes(i). LBound and UBound let the loop follow the declared bounds instead of assuming that every array starts at zero.

$ fbc -lang fb arrays.bas
$ ./arrays
 2 3 5 7 11

Functions

A function takes parameters, computes a value, and returns it with the Return statement. The return type follows As after the parameter list.

functions.bas
Function Add(a As Integer, b As Integer) As Integer
    Return a + b
End Function

Dim x As Integer = 4
Dim y As Integer = 5
Dim z As Integer = Add(x, y)
Print "Output: "; z

Add declares two integer parameters and an integer result. Add(x, y) passes the values four and five to those parameters. Return a + b ends the call and supplies the result, which is stored in z. In the fb dialect these numeric parameters default to ByVal: changing them would not change x or y. Write ByRef explicitly when a procedure must modify the caller's variable.

$ fbc -lang fb functions.bas
$ ./functions
Output:  9

Subroutines

A Sub performs an action but returns no value.

sub.bas
Sub SayHello(ByVal personName As String)
    Print "Hello, "; personName; "!"
End Sub

SayHello("Robert")

The argument "Robert" supplies the value of personName. The subroutine prints the greeting and returns to the statement after the call. Unlike Add, it cannot be used as a value in an assignment. ByVal explicitly passes the string by value; without a passing-mode qualifier, String parameters default to ByRef in this dialect. Exit Sub can end a call early.

$ fbc -lang fb sub.bas
$ ./sub
Hello, Robert!

User-defined types

A Type groups several fields under one name. Fields are accessed with the dot operator.

full.bas
Type Person
    personName As String
    age As Integer
End Type

Function Greet(p As Person) As String
    Return "Hello, " & p.personName & " (" & Str(p.age) & ")"
End Function

Dim people(0 To 1) As Person
people(0).personName = "Anna" : people(0).age = 31
people(1).personName = "Bob"  : people(1).age = 45

For i As Integer = 0 To 1
    Print Greet(people(i))
Next

Person defines a record with a string field and an integer field. The people array contains two such records. A colon separates two statements on one line; for example, the first pair of assignments initializes Anna's two fields. Unlike a numeric parameter, a user-defined-type parameter such as p As Person defaults to ByRef.

Greet reads the fields and returns a string. The & operator concatenates strings, while Str(p.age) converts the age to text. This avoids the extra numeric-printing space seen in earlier examples. The loop calls the function once for each record and prints the returned greeting.

$ fbc -lang fb full.bas
$ ./full
Hello, Anna (31)
Hello, Bob (45)

These examples introduce the core syntax. The individual tutorials on declarations, reference parameters, and dynamic arrays explain those topics in more detail.

Source

FreeBASIC documentation

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all FreeBasic Tutorials.