Futurebasic/language/variables
Variables
editIn FB, a variable can be thought of as a named container for data. The "container" has a specific size and (usually) a specific address in memory. Also, each variable has a specific type which determines how FB interprets its contents. You can copy data into a variable by putting the variable on the left side of the "=" symbol in a LET
statement; or by explicitly modifying the contents at the variable's address (through statements like POKE
and BLOCKMOVE
). Certain other FB statements and functions (such as SWAP
and INC
) may also modify a variable when you include the variable as a parameter. In FB, a variable can have any of the following forms:
identifier[tiSuffix]
A simple string or numeric variable, such as:myLong&
, ortheString$
.tiSuffix
is the optional type-identifier suffix, such as "$
", "%
", "&
", etc. See theDIM
statement, and Data Types and Data Representation, for a complete list of type-identifier suffixes. Examples:myIntVar xyz&
stringVar$[offset]
(Note: the square brackets are part of the variable)
This variable consists of the single byte which is located atoffset
bytes past the beginning of the string variablestringVar$
. (The$
is required) This variable's type isUNSIGNED BYTE
. This kind of variable is normally used to quickly retrieve or alter a single character in a string. The statement, "x=stringVar$[offset]
" is equivalent to: "x=PEEK(@stringVar$+offset)
". The statement, "stringVar$[offset]=x
" is equivalent to: "POKE@stringVar$+offset,x
". Examples:firstname$[3]
pointerVar
A pointer variable. This is an identifier declared as aPOINTER
type; it can be declared either as a "generic" pointer, or a pointer to some other specific type. Examples:myPtr anotherPtr
handleVar
A handle variable. This is an identifier declared as aHANDLE
type; it can be declared either as a "generic" handle, or a handle to some other specific type. Examples:myHandle thisHdl
recordName
The variable is an entire record. This can be either a "pseudo-record" (declared usingDIM recordName.constant
), or a "true record" (declared usingDIM recordName AS recordType
). Examples:myTrueRec iopb
arrayName[tiSuffix](expr1 [,expr2...])
The variable is a specific element of an array. This can be an array of any type, buttiSuffix
can only be used in numeric or string arrays. Note that an entire array is not considered to be a variable. Examples:firstName$(15) recArray(3, x%)
pseudoRecordName.const1[.const2...]tiSuffix
This variable consists of the bytes located at a specific offset from the beginning of a "pseudo-record."const1
,const2
etc. are previously-defined non-negative symbolic constant names (minus their leading undersorce character), or non-negative integer literals. The address of this variable is at (const1
+const2
+ ...) bytes past the beginning of the pseudo-record. The size and type of this variable are determined bytiSuffix
(for example, iftiSuffix
is "&
", then the variable is a 4-byte signed long integer). Examples:House.streetName$ pBlock.ioDrUsrWds.frRect.left%
psRecArray.const1[.const2...]tiSuffix(expr1 [,expr2...])
This variable consists of the bytes located at a specific offset from the beginning of a specific element in an array of "pseudo-records." The address of this variable is at (const1
+const2
+ ...) bytes past the beginning of the array element. The size and type of this variable are determined bytiSuffix
. Examples:HouseArray.streetName$(42,6) pb.rect.bottom%(z)
addressVar&.const1[.const2...]tiSuffix
The variable consists of the bytes located at a specific offset from the address given inaddressVar&
. The address of this variable is at (const1
+const2
+ ...) bytes past the given address; the size and type of this variable are determined bytiSuffix
.addressVar&
must be a (signed or unsigned) long-integer variable, or a genericPOINTER
variable.addressVar&
must be a "simple" variable; it cannot be an array element nor a record field. Examples:recPtr&.myField%` genericPtr.rectangle.right%
handleVar&..const1[.const2...]tiSuffix
The variable consists of the bytes located at a specific offset from the beginning of the relocatable block referenced byhandleVar&
. The address of this variable is at (const1
+const2
+ ...) bytes past the beginning of the block. The size and type of this variable are determined bytiSuffix
.handleVar&
must be a (signed or unsigned) long-integer variable, or a genericHANDLE
variable.handleVar&
must be a "simple" variable; it cannot be an array element nor a record field. Examples:recHdl&..thisField.thatField$ genericHandle..someField``
Variables Involving Fields of "true records"
editThe fields of a "true record" are defined inside a BEGIN RECORD
...END RECORD
block. A field's declared data type can be any valid type; if a field is itself declared as another "true record" type, then the field can have "subfields," which are just the fields of that secondary record.
A field can also be declared as an array (of any type). In this case, whenever the field's name is included as part of a variable specification, it must be followed by subscript(s) in parentheses. Thus, in each of the variable descriptions listed below, each field
and subfield
takes one of the following forms, depending on whether or not it's an array field.
For non-array fields:
field/subfield ::= fieldName[tiSuffix]
For array fields:
field/subfield ::= fieldName[tiSuffix](sub1 [,sub2...])
The type and size of each of the following variables is just the type and size of the last field
or subfield
specified.
trueRecordName.field[.subfield ...]
The variable is the specified field or subfield of the specified "true record." Examples:myTrueRec.myField% stats.game(7).teamName$(1)
recordPtr.field[.subfield ...]
The variable is the specified field or subfield of the "true record" pointed to byrecordPtr
. TherecordPtr
must be declared as a pointer to a specific type of record. Examples:ptr1.myField ptr2.arrayField$(3)
recordHdl..field[.subfield ...]
The variable is the specified field or subfield of the "true record" referenced byrecordHdl
. TherecordHdl
must be declared as a handle to a specific type of record. Examples:Hdl1..book(3).title$ Hdl2..phoneNum
arrayName(expr1[,expr2 ...]).field[.subfield ...]
This variable is the specified field or subfield of a specific element in an array of "true records." Examples:
HouseArray(42,6).streetName$ season(2).game(3).player(6)
ptrArray(expr1[,expr2 ...]).field[.subfield ...]
This variable is the specified field or subfield in a "true record" pointed to by an element in an array of pointers. The array must be declared as an array of pointers to a specific type of record. Examples:myPtrArray(n).field3& ptrArray(6,2).miscInfo.chapter(7).title$
handleArray(expr1[,expr2 ...])..field[.subfield ...]
This variable is the specified field or subfield in a "true record" referenced by an element in an array of handles. The array must be declared as an array of handles to a specific type of record. Examples:myHndlArray(7,j)..map myHndlArray(7,j)..map.quadrant(x,3).icon&
Limitations
editThere are some limitations on how many variables can be assigned.
- Arrays are limited to about 2 gigabytes (each).
- Simple variables inside of a local function are limited to 32K (per local function). In FBtoC the limit for local arrays is the same of global arrays (2 gigabytes). (See Why translate to C when I code in BASIC? ).
- The
.MAIN
file of a project often allocates variables outside of local functions that are not global. These are treated as variables for a local function and are limited to 32K. In FBtoC the limit is the same of global arrays (2 gigabytes).