Lolo89
Lolo89

Reputation: 3

CODESYS: Can I assign and array to another array?

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].

Upvotes: 0

Views: 797

Answers (1)

Guiorgy
Guiorgy

Reputation: 1734

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:

Results

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:

Results2

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:

Results3

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:

  • It assumes passed arguments are both arrays, even though you can pass anything. If you decide to make use of it, I recommend checking the TypeClass values of the passed arguments.
  • It assumes arrays are 1 dimensional, or if multidimensional, then the bounds of each dimension must match, otherwise the resulting order will be wrong.
  • It assumes array elements are of the same type.
  • It assumes array elements are value types, in other words, not pointers/references. If arrays of pointers are used, pointers will be copied, but underlying values the pointers point to will remain the same, so be careful.

Upvotes: 2

Related Questions