# Futurebasic/language/variables
## Variables

In 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&, or theString$. tiSuffix is the optional type-identifier suffix, such as "$", "%", "&", etc. See the DIM 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 at offset bytes past the beginning of the string variable stringVar$. (The $ is required) This variable's type is UNSIGNED 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 a POINTER 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 a HANDLE 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 using DIM recordName.constant), or a "true record" (declared using DIM 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, but tiSuffix 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 by tiSuffix (for example, if tiSuffix 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 by tiSuffix. 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 in addressVar&. The address of this variable is at (const1 + const2 + ...) bytes past the given address; the size and type of this variable are determined by tiSuffix. addressVar&must be a (signed or unsigned) long-integer variable, or a generic POINTER 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 by handleVar&. 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 by tiSuffix. handleVar& must be a (signed or unsigned) long-integer variable, or a generic HANDLE 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"

The 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:
For array fields:
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 by recordPtr. The recordPtr 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 by recordHdl. The recordHdl 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

There 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).