====== Variables ====== 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. Example: 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. ===== Types ===== 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 ((Using the # sigil for specifying integer type is DEPRECATED and will be removed in the future)) | -32768 to +32767 |2| | Float | % | ±2.93873588E−39 to ±1.70141183E38|5| | 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: - If at least one member of an expression is a //float//, every other members will be converted to //float//. - Otherwise if at least one member of an expression is an //integer//, every other members will be converted to //integer//. Example: 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 ===== 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|CONST]] statement for more information. ===== Scope ===== 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|PROC ... ENDPROC]] statements for more details.