Roald
Roald

Reputation: 2979

How to assign an initialized array to an array of arrays in TwinCAT

I'm trying to assign two initialized arrays evenNumbers and oddNumbers to an array of arrays integers:

PROGRAM ArrayInit
VAR
    evenNumbers : ARRAY[1..3] OF INT := [2, 4, 6];
    oddNumbers: ARRAY[1..3] OF INT := [1, 3, 5];
    
    integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
END_VAR

This code gives me a compiler error

Array initialisation expected

Of course I can directly initialize integers with the numbers that I want like so:

PROGRAM ArrayInit
VAR
    integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [
        [2, 4, 6], [1, 3, 5]
    ];
END_VAR

or like Sergey mentioned

PROGRAM ArrayInit
VAR
    integers: ARRAY[1..2, 1..3] OF INT := [
        2, 4, 6, 1, 3, 5
    ];
END_VAR

However, if the original arrays are very big and/or I want to document what these different arrays are, a descriptive name would be nice. I.e. integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers]; nicely shows that the integers has two lists, one with even and one with odd numbers.

I've also tried to initialize integers as integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [[evenNumbers], [oddNumbers]];, but this gives me the compiler error:

Cannot convert type 'ARRAY [1..3] OF INT' to type 'INT'

Now I wonder if it even possible? If so, does anyone know how I can do it?

Upvotes: 4

Views: 3542

Answers (3)

Felix
Felix

Reputation: 1189

Your line integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers]; works fine when evenNumbers and oddNumbers are constants. You cannot use non-constant variables to initialize other variables.

In case you need evenNumbers and oddNumbers to be changed later, you could create two constants evenNumbersConst and oddNumbersConst and use them just for the initialization like so:

VAR
    evenNumbers : ARRAY[1..3] OF INT := evenNumbersConst;
    oddNumbers  : ARRAY[1..3] OF INT := oddNumbersConst;    
    integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbersConst, oddNumbersConst];
END_VAR

VAR CONSTANT
    evenNumbersConst : ARRAY[1..3] OF INT := [2, 4, 6];
    oddNumbersConst  : ARRAY[1..3] OF INT := [1, 3, 5];
END_VAR

Upvotes: 3

Guiorgy
Guiorgy

Reputation: 1734

I don't think you can join arrays while initializing a third (see the edit below). What you can do however is call a function at the start of the program once that joins those two arrays:

PROGRAM PLC_PRG
VAR
    arr1: ARRAY [0..2] OF INT := [1, 2, 3];
    arr2: ARRAY [0..2] OF INT := [4, 5, 6];
    arr3: ARRAY [0..5] OF INT;
    initialized: BOOL := FALSE;
END_VAR

IF (NOT initialized) THEN
    initialized := TRUE;
    JOIN_INT_ARRAYS(arr1 := arr1, arr2 := arr2, dest_arr := arr3);
END_IF
// Assume that:
//      - the destination ARRAY size can fit all source ARRAYs
//      - all ARRAYs store INTs
FUNCTION JOIN_INT_ARRAYS
VAR CONSTANT
    size_of_int: DWORD := SIZEOF(INT);
END_VAR
VAR_IN_OUT
    arr1: ARRAY [*] OF INT;
    arr2: ARRAY [*] OF INT;
    dest_arr: ARRAY [*] OF INT;
END_VAR
VAR
    arr1_len: DWORD := DINT_TO_DWORD(UPPER_BOUND(arr1, 1) - LOWER_BOUND(arr1, 1) + 1) * size_of_int;
END_VAR

MEMUtils.MemCpy(pbySrc := arr1, pbyDest := dest_arr, dwSize := arr1_len);
MEMUtils.MemCpy(pbySrc := arr2, pbyDest := dest_arr + arr1_len, dwSize := DINT_TO_DWORD(UPPER_BOUND(arr2, 1) - LOWER_BOUND(arr2, 1) + 1) * size_of_int);

Result:

result.png

A few things to note:

  • I used the MemCpy function from the MEMUtils library. If you don't have it, or don't want to add it into your project, you can manually copy values from one array into another using a FOR loop.
  • I have omitted range checking, which can be extremely dangerous. If you want extra protection, then add it yourself.
  • avoid passing arr_dest as arr1 or arr2. Trying to copy from an array into itself may lead into problems.

EDIT:

Actually, this seems to work:

integers: ARRAY [0..1] OF ARRAY [0..2] OF INT := [[2, 4, 6], [1, 3, 5]];
evenNumbers: ARRAY [0..2] OF INT := integers[0];
oddNumbers: ARRAY [0..2] OF INT := integers[1];

result:

result1.png

But I don't know if this is your desired outcome. If you want a continuous array as the combined array, then you can try this:

// in Program
evenNumbers: ARRAY [0..2] OF INT := [2, 4, 6];
oddNumbers: ARRAY [0..2] OF INT := [1, 3, 5];
integers: ARRAY [0..5] OF INT := JOIN_INT_ARRAYS_3_3_6(arr1 := evenNumbers, arr2 := oddNumbers);
// (left)3 + (right)3 = (result)6
FUNCTION JOIN_INT_ARRAYS_3_3_6 : ARRAY [0..5] OF INT
VAR_IN_OUT
    arr1: ARRAY [0..2] OF INT;
    arr2: ARRAY [0..2] OF INT;
END_VAR
VAR
    i: USINT;
END_VAR

FOR i := 0 TO 2 DO
    JOIN_INT_ARRAYS_3_3_6[i] := arr1[i];
END_FOR
FOR i := 0 TO 2 DO
    JOIN_INT_ARRAYS_3_3_6[i + 3] := arr2[i];
END_FOR

and the result:

result2.png

However, with this method the function can't be general, so you will have to modify it's input and output array sizes every time the conditions change, and create many if you want to use this in several places, thus it's not elegant, and personally I'd avoid it, but if this works for you, then here it is.

Also, this seems to give me a C0441: Access to uninitialized VAR_IN_OUT variable warning, so another reason to try to avoid it.

Upvotes: 2

Sergey Romanov
Sergey Romanov

Reputation: 3080

To assign multiple level array you do it in one line.

combinedSet : ARRAY[1..2, 1..2] OF INT := [1,2,3,4];

will result in array

[
  1 => [
     1 => 1, 
     2 => 2
  ],
  2 => [
     1 => 2, 
     2 => 4
  ]
]

SO first it assign all element of first element [1, 1], [1, 2], [1, 3] ... and then nest one [2, 1], [2, 2], [2, 3] ...

Additional information

Most simple way to merge 2 arrays into one multi dimensional is:

PROGRAM PLC_PRG
    VAR
        arr1 : ARRAY[1..3] OF INT := [1,3,5];
        arr2 : ARRAY[1..3] OF INT := [2,4,6];
        combinedSet : ARRAY[1..2] OF ARRAY[1..3] OF INT;
    END_VAR
    
    combinedSet[1] := arr1;
    combinedSet[2] := arr2;
END_PROGRAM

The reason this does not work

integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];

Because evenNumbers and oddNumbers are not initialized at the moment of use. If you would declare those in VAR CONSTANT it would probably work but then you would not be able to change content of those arrays in program.

Upvotes: 4

Related Questions