SA0066: Use of temporary results

Function

Determines applications of intermediate results in statements with a data type that is smaller than the register size. In this case, the implicit cast may lead to undesirable results.

Reason

For performance reasons, TwinCAT carries out operations across the register width of the processor. Intermediate results are not truncated! This can lead to misinterpretations, as in the following case:

usintTest := 0;
bError := usintTest - 1 <> 255;

In TwinCAT, bError is TRUE in this case, because the operation usintTest - 1 is typically executed as a 32-bit operation and the result is not cast to the size of bytes. In the register the value 16#ffffffff is then displayed and this is not equal to 255. To avoid this, you have to explicitly cast the intermediate result:

bError := TO_USINT(usintTest - 1) <> 255;

Importance

Low

SA0066: Use of temporary results 1:

If this message is enabled, a large number of rather unproblematic situations in the code will be reported. Although a problem can only arise if the operation produces an overflow or underflow in the data type, the Static Analysis cannot differentiate between the individual situations.

If you include an explicit typecast in all reported situations, the code will be much slower and less readable!

Sample:

PROGRAM MAIN
VAR
    nBYTE   : BYTE;
    nDINT   : DINT;
    nLINT   : LINT;
    bResult : BOOL;
END_VAR
//=====================================================================================================
// type size smaller than register size
// use of temporary result + implicit casting => SA0066
bResult := ((nBYTE - 1) <> 255);                           // => SA0066
 
// correcting this code by explicit cast so that the type size is equal to or bigger than register size
bResult := ((BYTE_TO_LINT(nBYTE) - 1) <> 255);             // no error
bResult := ((BYTE_TO_LINT(nBYTE) - LINT#1) <> LINT#255);   // no error
 
//=====================================================================================================
// result depends on solution platform
bResult := ((nDINT - 1) <> 255);                           // no error on x86 solution platform
                                                           // => SA0066 on x64 solution platform
 
// correcting this code by explicit cast so that the type size is equal to or bigger than register size
bResult := ((DINT_TO_LINT(nDINT) - LINT#1) <> LINT#255);   // no error
 
//=====================================================================================================
// type size equal to or bigger than register size
// use of temporary result and no implicit casting => no error
bResult := ((nLINT - 1) <> 255);                           // no error
 
//====================================================================================================