Typed Literals
When you use constant literal numbers in an ST program, they are automatically assigned a type. The type that is assigned is the integer type that has the lowest range that can support the literal number. For example, if you enter 200 as a constant literal, the 200 will automatically be assigned a USINT integer type (SINT integers only support -128 to 127, so cannot be used. USINT is the next lowest integer type and as it supports 0 to 255, it can be used).
The result of a calculation that uses constant literals is also assigned a type automatically. The integer type that is assigned to the result matches the integer type with the highest range in the expression. So, if the expression is 150+400, the result is assigned the INT integer type (the 150 is assigned USINT and the 400 is assigned INT).
The automatic assigning of integer types can cause unexpected results, as the result of an expression may be a number that exceeds the range of the integer type for the result. This causes an overflow. For example, with the following program, you would expect the value of A to be 300 (the result of 100 x 3):
VAR
A : INT;
END_VAR
A := 100 * 3;
However, in this case, the value of A is 44, even though the integer type for A has been defined as INT, which supports 300. The reason for this is that in the expression 100*3, SINT is used for both 100 and 3 (as SINT supports the range -128 to 127). This means that the result of the expression is also SINT as it matches the integer type of the highest number in the expression. As the expected result of the expression is 300, this means there is an overflow - the result value exceeds the range supported by the result integer type. And so 100*300 results in 44. The 44 for the SINT result is then converted into an INT as declared for A at the start of the program.
ClearSCADA allows you to use typed literals to avoid this situation. By using typed literals, you can declare a specific integer type for each constant literal in your program. When there is a declared integer type for a constant literal, the program uses the declared integer type; the smallest integer type is not assigned automatically.
To declare a specific integer type for a constant literal, you need to use the following syntax:
<Integer Type>#<Constant Literal>
Where:
- <Integer Type> is the integer type that will be assigned to the constant literal. Do not enter the angle brackets < >.
- <Constant Literal> is the number to be used in the expression. Do not enter the angle brackets < >.
So, if we take the example that we used before, 100*3, the program could be defined like this:
VAR
A : UINT;
END_VAR
A := INT#100 * 3;
As you can see, the 100 is declared as an INT whereas the 3 is assigned a SINT automatically (the lowest integer type that supports 3). The code would also produce the expected result if the 100 was SINT and the 3 was INT or if both 100 and 3 were INT. This is because one of the constant literals has to be of an integer type that is also large enough to support the expected result.
So, as the expression has an INT and a SINT for its constant literals, the result is assigned an INT (the highest integer type used by the constant literals in the expression). The expected result of the expression - 300 - is supported by integer type of the result (INT, which supports -32, 768 to +32, 767). This means that the result of the expression does not overflow and is the expected 300.
The result of 300 is then converted from INT to UINT as A was declared as a UINT at the start of the program. As UINT supports the range 0 to 65,535, the 300 value is stored by the A variable. However, had the integer type of A been declared as an integer type that does not support the result of 300, the value for A would be truncated. To obtain the expected result, you need to use appropriate integer types for:
- The result of the expression in the program. Remember that it is assigned the same type of integer as the highest integer type used by the constant literals in the expression.
- The variable that is used to store the result of the expression. The variable has to be assigned an integer type that supports the expected result of the expression, otherwise the expression may produce the correct result but the result will be stored as a truncated value.
Further Information