You're browsing the old v2.x documentation. This version is no longer maintained. Click here to go the v3.x documentation.


Variables in XC=BASIC are statically allocated memory areas that are assigned an identifier (name) and a type that can not be changed.

Variable definition

Variables don't need to be explicitly defined. The compiler will create the variable the first time it encounters them in a LET, DIM or DATA statement.


let a = 1
rem -- a is now defined
print a
rem -- the following is invalid because b is used prior to being defined
print b
let b = 2

Fast variables

Since version 2.1, some variables can be placed on the zeropage for faster load/store operations. You can use the DIM directive to define a variable as fast variable, for example:

dim myFastVar fast

This is limited however (max 15 bytes currently). The compiler will emit a warning if no more variables can be placed on the zeropage.


The type of a variable is specified using a sigil that is appended to the variable name. If omitted, the variable will be recognized as integer. The following types are supported:

Type Sigil Numeric range Size in bytes
Byte ! 0 to 255 1
Integer # or none 1) -32768 to +32767 2
Float % ±2.93873588E−39 to ±1.70141183E385
String pointer $ 0 to 65535 2

Type conversion

Implicit conversion

If different types take part of an expression, all members of the expression will be implicitly promoted to the larger type and a warning will be emitted in compile time. This means that:

  1. If at least one member of an expression is a float, every other members will be converted to float.
  2. Otherwise if at least one member of an expression is an integer, every other members will be converted to integer.


let anInt = 5
let anotherInt = 6
let aFloat% = 3.14
print anInt + anotherInt + aFloat%
rem -- the above expression will return a float while anInt and anotherInt 
rem -- will be promoted to floats

The above program will compile fine, with a warning:

Warning: implicit type conversion in line 4

Implicit conversion from byte to integer does not emit a warning.

An important note about sub-expression casting

A parenthesized sub-expression is considered to be a single member of its parent expression. Implicit type casting does not apply to members of the sub-expression. Take the following code sniplet for example:

  anInteger = 4
  aByte! = 255
  anotherByte! = 1
  result = anInteger * (aByte! + anotherByte!)

You may expect that someByte and anotherByte will be converted to integers first and then their sum will be multiplied with anInteger. This is not how it will work though. The expression will be evaluated as follows:

  • The parenthesized expression is evaluated. Both of its members are bytes, so the whole expression (aByte! + anotherByte!) is evaluated as byte. The numbers are added up, and an overflow occurs (255 + 1 = 0)
  • The outer expression is an integer, because one of its members (anInteger) is an integer. So the other member (which is now evaluated to 0) is converted to an integer and the two factors are multiplied. The result is 0.

To solve this problem you have to explicitly cast at least one of the members of the sub-expression to integer and thus the compiler will implicitly convert the other member, too:

  result = anInteger * (cast(aByte!) + anotherByte!)

Now the result will is 4 * (255 + 1) = 4 * 256 = 1024.

Explicit conversion

You can use the CAST() function to convert between different types. For example:

let aFloat% = 3.14
let anInt = cast(aFloat%)
rem -- the above will print 3

let anInt = 3
let aFloat% = cast%(anInt)
rem -- note you can't just "let aFloat% = anInt"

let anInt = 256
let aByte! = cast!(anInt)
rem -- the above will print 1 and you'll be warned of truncation


Constants are not variables in a sense that they do not reserve memory at all. However, you can use them just like a variable, except that they may not change value in runtime.

The benefit of using constants instead of variables are:

  • Constants do not reserve space in memory
  • Constants are faster to evaluate

Always prefer constants over variables, whenever possible. See the documentation for the CONST statement for more information.


Variables, constants and labels can be global or local.

Any variable or constant declared using a CONST, LET, DIM or DATA statement outside a PROC … ENDPROC pair is considered to be a global variable and are only accessible within a procedure by using the global modifier (\).

Any variable or constant declared using a CONST, LET, DIM or DATA statement inside a PROC … ENDPROC pair, including the procedure's parameters, is considered to be a local variable and can only be accessed within that procedure.

Please see the documentation for the PROC ... ENDPROC statements for more details.

Using the # sigil for specifying integer type is DEPRECATED and will be removed in the future