One of the mistakes I often make in TwinCAT is that I mistake arrays for reference types. Which arrays are for example in C#. However in TwinCAT arrays are value types! Which means that when we assign ‘:=’ one array to another, we don’t take its reference address but copy all individual elements to the target!
Consider this code:
PROGRAM MAIN VAR int_array:ARRAY[0..2] OF INT:=[1,2,3]; int_array2:ARRAY[0..2] OF INT; END_VAR
int_array2 := int_array; int_array2:= 100;
Notice that the elements are copied. But the arrays ‘int_array’ and ‘int_array2’ are not the same element! Changing a single index in one array doesn’t change the value at the other array.
With a small number of elements or non-complex structures copying is not a problem, however with large array this might cause an severe performance penalty!
Consider a function which takes an array as input, modifies the contents and returns an array:
FUNCTION ModifyArray:ARRAY[0..1000] OF INT VAR_INPUT Input :ARRAY[0..1000] OF INT; END_VAR VAR i:INT; END_VAR
FOR i:=0 TO 1000 DO ModifyArray[i] := Input[i] + 1; END_FOR
ArrayToModfiy := ModifyArray(ArrayToModfiy);
The problem here is that the PLC has to copy all elements in the array twice! First to copy the variable ‘ArrayToModify’ to the function, and after processing to get the processed value back in ‘ArrayToModify’. In such case it might be a better choice to pass the array as VAR_IN_OUT, or as input pointer:
FUNCTION ModifyArray VAR_IN_OUT Input :ARRAY[0..1000] OF INT; END_VAR VAR i:INT; END_VAR
FOR i:=0 TO 1000 DO Input[i] := Input[i] + 1; END_FOR
For much better performance! This is the reason that I for example in the post a Code Jam challenge with ST. I used VAR_IN_OUT for passing the bigger arrays to the different functions and methods!
In TwinCAT arrays are value types.
Happy coding 🙂