Comparison of Static and Dynamic Arrays
A static array variable holds a value of type, array. A dynamic array variable holds a pointer to an array value. Thanks to automatic pointer dereferencing and automatic index padding, there is very little difference in the code that you write to use either type of array. What differences do exist can be found in the following technical points.
It is important to note that use of a static array where a function expects a dynamic array, will result in that function failing to work properly.
Use dynamically allocated arrays for all code unless a function reference explicitly states that a static array is expected for one of the parameters.
Static arrays are created in the variable declaration StaticArray[50];, whereas dynamic arrays are created using the New() function within a script block.
Automatic Pointer Dereferencing
Since dynamic array variables are pointers, one might expect to do a lot of pointer dereferencing when using dynamic arrays. For example, to access the fourth element of a dynamic array pointed to by DynamicArray, one might expect to write the following code:
(*DynamicArray)[4] = 0;
While this syntax is correct, it is also redundant; whenever VTScada encounters the [ ] index operator, it automatically dereferences the variable being indexed. This makes the explicit dereferencing unnecessary, so that the above code can simply be written as:
DynamicArray[4] = 0;
By automatically dereferencing an array pointer under these circumstances, VTScada makes accessing an element of a dynamic array look and behave just like accessing an element of a static array.
StaticArray[4] = 0;
Note: VTScada only performs automatic dereferencing when an element is accessed with the index operator. In no other cases is a dynamic array automatically dereferenced.
Automatic Index Padding
Unlike its automatically dereferenced pointers, VTScada's automatically padded indices makes for array-related code that looks the same, but behaves differently, depending on whether a dynamic array or a static array is used. This mismatch between appearance and workings can easily lead to developer confusion, and thus warrants special attention.
VTScada applies automatic index padding whenever an array reference is under-specified. In turn, an array reference is considered under-specified if two criteria are met:
- The array reference must involve an array value, as opposed to a pointer to an array value. This is almost the same as saying the array reference must involve a static array variable, as opposed to a dynamic array variable, with two exceptions:
- Whenever a dynamic array variable is explicitly dereferenced (*DynamicArray), the result is an array value.
Similarly, whenever a dynamic array is referenced with the [ ] operator, VTScada automatically dereferences the array pointer, and the result is an array value.
- An array reference must include fewer [ ] operators than the referenced array has dimensions.
5. StaticArray; { Under-specified } 6. &StaticArray; { Not under-specified, not an array value } 7. StaticArray[2]; { Under-specified } 8. StaticArray[1][3]; { Not under-specified }
Lines 2 and 5 show the inconspicuous difference between dynamic and static arrays: VTScada considers line 2 fully specified, but considers line 5 under-specified.
x = StaticArray; { x = StaticArray[0][0] } x = &StaticArray; { x = StaticArray. See Variable Assignment } x = StaticArray[2]; { x = StaticArray[2][0] } x = StaticArray[1][3]; { x = StaticArray[1][3] }
Value Assignment - Static versus Dynamic Arrays
It is not possible to assign a value directly to (or from) a static array variable, and VTScada's automatic index padding ensures that this does not happen. If it ever appears that a static array is participating in an assignment, automatic index padding works to make sure that only an element of the array is involved. The following code shows the automatic index padding at work, with equivalent assignments in comments.
[ AStaticArray[3] = 1; BStaticArray[5][10] = 2; SimpleVar; ] Init [ If 1 Main; [ SimpleVar = AStaticArray; { SimpleVar = AStaticArray[0] } SimpleVar = BStaticArray[4]; { SimpleVar = BStaticArray[4][0] } SimpleVar = BStaticArray[3][1]; { SimpleVar = BStaticArray[3][1] } SimpleVar = &AStaticArray; { SimpleVar = &AStaticArray } AStaticArray = "super"; { AStaticArray[0] = "super" } BStaticArray[4] = 3; { BStaticArray[4][0] = 3 } BStaticArray[3][1] = 4; { BStaticArray[3][1] = 4 } &AStaticArray = 0x00008000; { Error! Not an lvalue } AStaticArray = BStaticArray; {AStaticArray[0] = BStaticArray[0][0] } ] ]
Dynamic-array variables are declared no differently than any other VTScada variable. This similarity carries over to assignment, where assigning a value to (or from) a dynamic-array variable is no different than assigning a value to (or from) any other VTScada variable. Dynamic-array variables can be assigned any scalar value, including another dynamic-array variable (a pointer to an array). The following code shows these assignments.
If 1 Main; [ ADynamicArray = 5; { a scalar assignment } ADynamicArray = New(3, 2); { a new dynamic array } BDynamicArray = ADynamicArray[1]; { under-specified. ADynamicArray[1][0] is assigned instead } BDynamicArray = "super"; { another scalar assignment } CDynamicArray = New(10); { a new dynamic array } DDynamicArray = CDynamicArray; { one dynamic array to another } SimpleVar = DDynamicArray; { a dynamic array to a simple variable } ]
When a dynamic-array variable is assigned to another variable, as in the last two assignments of the previous example, only the pointer is assigned, and no arrays are copied: in the previous example, CDynamicArray, DDynamicArray, and SimpleVar all point to the same dynamically allocated ten-element array.
Note than during these assignments, neither of VTScada's automatic array-related features was invoked: no [] index operators were present and none of the array references were under-specified.
Passing an Array to a Module
Arguments to a Launched Module (or subroutine) are passed by value (i.e. the value of the argument is copied, or assigned, to the module's parameter). For this reason, passing arguments to a launched module is very similar to assigning a value to a variable. It should be no surprise, then, that the rules that govern passing arguments to launched modules are identical to those that govern variable assignment: VTScada uses automatic index padding to ensure that only an element of a static array is passed to a launched module, while passing dynamic arrays to launched modules is less restricted.
When arguments are passed to a Called Module, they are passed by reference (i.e. a called module's parameter is made to refer the argument, and no copy is made). This is the only case when a static-array reference is not index padded by VTScada. When a static array is passed to a called module, the called module's parameter is made to refer to the entire static array, and not just to one particular array element. Consequently, a called module can change the elements of a static-array argument, and any changes will appear outside of the module.
Similarly, when a dynamic array is passed to a called module, the array pointer is not copied to the module parameter, but rather the called module's parameter is made to refer to the array pointer (think of a pointer to a pointer). In this way, a called module can change not only the elements in, but also the size and dimensions of, a dynamic-array argument, and any changes will appear outside of the module.