Can I perform the following operation in codesys?
VAR
abVariable_A: ARRAY[0..15] OF BYTE := [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
abVariable_B: ARRAY[1..16] OF BYTE := [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
END_VAR
abVariable_B := abVariable_A;
What would the result of abVariable_B
be?
Can I expect it to be equal to
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
Or I will get
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
Please pay attention to the dimension of the arrays, although both have a dimension of 16, the indexes don't start at the same point. Does this affect the assignation of the arrays?
I expect abVariable_B
to be equal to [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
.
We can do a simple experiment by running:
PROGRAM Test
VAR
abVariable_A: ARRAY[0..15] OF BYTE := [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
abVariable_B: ARRAY[1..16] OF BYTE := [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
pA_before: POINTER TO BYTE;
pB_before: POINTER TO BYTE;
pA_after: POINTER TO BYTE;
pB_after: POINTER TO BYTE;
END_VAR
pA_before := ADR(abVariable_A);
pB_before := ADR(abVariable_B);
abVariable_B := abVariable_A;
pA_after := ADR(abVariable_A);
pB_after := ADR(abVariable_B);
END_PROGRAM
And observing the result:
As we can see, the values in both arrays are the same, and array addresses didn't change (that means all values were copied, instead of just the array reference/pointer like in many other languages).
We can double check that the values were copied and that the arrays don't point to the same array by modifying one of the values in one array:
abVariable_B := abVariable_A;
abVariable_B[3] := 255;
And observing the result:
This experiment shows that codesys treats array assignment as a memory copy for all values (at least in CODESYS 3.5.16, haven't tested this on older versions).
The initial index has absolutely no importance to the underlying memory layout of an array, it is just there for programmers convenience. However, the same can't be said about arrays of different length:
abVariable_A: ARRAY[0..15] OF BYTE := [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
abVariable_B: ARRAY[1..18] OF BYTE := [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
Results in the C0032: Cannot convert type 'ARRAY [0..15] OF BYTE' to type 'ARRAY [1..18] OF BYTE'
error when we try to assign abVariable_A
to abVariable_B
.
Simmilar error is shown if abVariable_A
is larger than abVariable_B
.
If don't trust the built-in array assignment, or want to handle the above cases, where the arrays have different lengths, you could create a custom function, for example:
FUNCTION ArrayCopy
VAR_INPUT
destination: ANY;
source: ANY;
END_VAR
MEMUtils.MemCpy(pbyDest := destination.pValue, pbySrc := source.pValue, MIN(destination.diSize, source.diSize));
END_FUNCTION
If we use it instead of the assignment:
ArrayCopy(abVariable_B, abVariable_A);
abVariable_B[3] := 255;
The result is as expected:
Though, keep in mind, the function above requires the MemoryUtils library, and is just an example. Although it works with arrays of any type, it has drawbacks:
TypeClass
values of the passed arguments.