Variables: Difference between revisions
Lou Montana (talk | contribs) (Page refresh) |
Lou Montana (talk | contribs) m (Add a spawn due to peer pressure) |
||
Line 22: | Line 22: | ||
Before [[{{arma2}}]], querying undefined (or uninitialised) variables returns [[nil]] (undefined value); from [[{{arma2}}]] and later, it returns an "Error Undefined variable in expression" error. | Before [[{{arma2}}]], querying undefined (or uninitialised) variables returns [[nil]] (undefined value); from [[{{arma2}}]] and later, it returns an "Error Undefined variable in expression" error. | ||
{{Informative | An undefined ([[nil]]) variable converted to [[String]] with | {{Informative | An undefined ([[nil]]) variable converted to [[String]] with [[str]] will return [[scalar bool array string 0xe0ffffef]] (in [[Armed Assault]]) and [[scalar bool array string 0xfcffffef]] (in [[Operation Flashpoint]]).<br> | ||
Unless trying to emulate [[isNil]], '''always''' declare your variable before trying to access it.}} | Unless trying to emulate [[isNil]], '''always''' declare your variable before trying to access it.}} | ||
Line 101: | Line 101: | ||
</tr> | </tr> | ||
<tr> | <tr> | ||
<td rowspan=" | <td rowspan="22" style="background-color: orange; border-radius: 10em"></td> | ||
<td></td> | <td></td> | ||
<td></td> | <td></td> | ||
<td></td> | <td></td> | ||
<td rowspan=" | <td rowspan="22"></td> | ||
<td>'''{{Color|darkorange|TAG_GlobalVariable}}''' = "Global variable"; {{cc|Global variable is accessible from any scope}}</td> | <td>'''{{Color|darkorange|TAG_GlobalVariable}}''' = "Global variable"; {{cc|Global variable is accessible from any scope}}</td> | ||
</tr> | </tr> | ||
Line 115: | Line 115: | ||
</tr> | </tr> | ||
<tr> | <tr> | ||
<td rowspan=" | <td rowspan="15" style="background-color: darkgreen; border-radius: 10em"></td> | ||
<td><wbr /></td> | <td><wbr /></td> | ||
<td><wbr /></td> | <td><wbr /></td> | ||
Line 172: | Line 172: | ||
<td></td> | <td></td> | ||
<td></td> | <td></td> | ||
<td>[[hint]] [[str]] _myVariable; {{cc|if '''{{Color|grey|_condition}}''' is [[true]], _myVariable's value is '''{{Color|darkgreen|1}}''';}}</td> | <td>[[hint]] [[str]] '''{{Color|darkgreen|_myVariable}}'''; {{cc|if '''{{Color|grey|_condition}}''' is [[true]], _myVariable's value is '''{{Color|darkgreen|1}}''';}}</td> | ||
</tr> | </tr> | ||
<tr> | <tr> | ||
<td></td> | <td></td> | ||
<td></td> | <td></td> | ||
<td> | <td> {{cc|if '''{{Color|grey|_condition}}''' is [[false]], _myVariable's value is '''{{Color|darkgreen|4}}'''.}}</td> | ||
</tr> | |||
<tr> | |||
<td></td> | |||
<td></td> | |||
<td><wbr /></td> | |||
</tr> | |||
<tr> | |||
<td></td> | |||
<td></td> | |||
<td>['''{{Color|darkgreen|_myVariable}}'''] [[spawn]] {</td> | |||
</tr> | |||
<tr> | |||
<td></td> | |||
<td></td> | |||
<td></td> | |||
<td> [[hint]] [[str]] _myVariable; {{cc|will throw an [[Debugging Techniques#Common errors|"undefined variable" error]], as '''{{Color|darkgreen|_myVariable}}''' does '''not''' exist in this (new) scope!}}</td> | |||
</tr> | |||
<tr> | |||
<td rowspan="4" style="background-color: darkgreen; border-radius: 10em"></td> | |||
<td></td> | |||
<td></td> | |||
<td>};</td> | |||
</tr> | </tr> | ||
<tr> | <tr> | ||
Line 196: | Line 218: | ||
</table> | </table> | ||
{| style="margin: auto" | {| style="margin: auto" |
Revision as of 15:46, 14 May 2020
A variable is a "storage container" or "named placeholder" for data. You can read and modify the data once this container is created.
Its "name" is referenced as Identifier.
Requirements
The following links guide to the basics to understand this article:
Initialization
The first thing to do to create a variable is to find its name, also called identifier; this name must be speaking to the reader - keep in mind that code is meant to be read by human beings (see Code Best Practices - Variable format).
Once a proper name is found, it can be used to declare (or initialise) the variable:
myVariable = 0;
Before Arma 2, querying undefined (or uninitialised) variables returns nil (undefined value); from Arma 2 and later, it returns an "Error Undefined variable in expression" error.
Deletion
Once created, variables take up space in the computer's memory.
This is not drastic for small variables, but if a big number of very large variables is used, it is recommended to undefine the unneeded ones in order to free up memory. This can be done by setting their value to nil.
HugeVariable = nil;
This effectively destroys a variable as if it had never existed.
Scopes
Variables are only visible in certain scopes of the game. This prevents name conflicts between different variables in different scripts.
There are two main scopes:
Global Scope
A global variable is visible from all scripts on the computer on which it was defined. Names given to units in the Mission Editor are also global variables pointing to those units, which may not be redefined or modified.
Local Scope
A local variable is only visible in the script, function or Control Structure in which it was defined.
Local Variables Scope
Local variables in callable code (e.g Functions) should be scoped using the command private, otherwise you may modify local variables of the calling script that are visible in the function.
// Since Arma 3 v1.54 private _myLocalVariable = 0; // From Arma 2 until Arma 3 v1.54 local _myLocalVariable = 0; // Before Arma 2 private "_myLocalVariable"; _myLocalVariable = 0; // Alternative method to private multiple local variables at the same time private ["_myLocalVariable1", "_myLocalVariable2"]; _myLocalVariable1 = 1; _myLocalVariable2 = 2;
If a private variable is initialised within a Control Structure (i.e. if, for, switch, while), its existence will be limited to it and its sub-structures - the variable does not exist outside of the structure and will be seen as undefined.
Variables lifespan |
Code | ||||
---|---|---|---|---|---|
TAG_GlobalVariable = "Global variable"; // Global variable is accessible from any scope | |||||
private _myVariable = 0; | |||||
if (_condition) then | |||||
{ | |||||
_myVariable = 1; | |||||
private _myVariable = 2; | |||||
_myVariable = 3; | |||||
} else { | |||||
_myVariable = 4; | |||||
private _anotherVariable = 10; | |||||
}; | |||||
hint str _myVariable; // if _condition is true, _myVariable's value is 1; | |||||
// if _condition is false, _myVariable's value is 4. | |||||
[_myVariable] spawn { | |||||
hint str _myVariable; // will throw an "undefined variable" error, as _myVariable does not exist in this (new) scope! | |||||
}; | |||||
// trying to use _anotherVariable here would result in an "undefined variable" error, | |||||
// _anotherVariable being only scoped in the else. |
Incorrect | Correct |
---|---|
|
private _living = false;
|
Data Types
Variables may store values of a certain Data Type (String, Number, etc). The kind of the value specifies the type of the variable. Different operators and commands require variables to be of different types.
A variable is not strongly typed and changes its type according to the new data:
private "_myVariable"; // nil _myVariable = 1; // 1 (Number) _myVariable = "test"; // "test" (String)
Multiplayer Considerations
Storing functions (or any callable code) into global variables without securing them with compileFinal (since Arma 3) is a very bad practice in multiplayer. The biggest security risk would be to see it being overridden by a malicious usage of publicVariable, setting potentially dangerous code in it.
The best option is to declare your function in CfgFunctions so the engine secures it for you.
If you want to manually create a global function anyway, the best practice is the following:
TAG_MyGlobalVariableFunction = compileFinal preprocessFileLineNumbers "functionFile.sqf";
See also
- Introduction to Arma Scripting
- Identifier
- Data Types
- Control Structures
- Magic Variables
- private (Arma 3)
- local (Arma 2)