Typisierung von Ausdrücken
logi.CAD 3 →typisiert →Ausdrücke und →Zuweisungen laut diesen Regeln:
Der Datentyp der →Variable, die das Ergebnis einer →überladenen Funktion erhält, beeinflusst den Datentyp des Ergebnisses für eine Funktion oder Operation. Diese Regel entspricht nicht den Vorgaben der →IEC-Norm.
BeispieleVAR
int1, int2, int3 : INT := 32767;
dint1 : DINT := 32767;
ResultInt1 : INT;
ResultDint1, ResultDint2 : DINT;
END_VAR
ResultInt1 := int1 + int2; (* Die Addition wird als INT-Operation durchgeführt. *)
ResultDint1 := int1 + int2; (* Unterschiedlich zur IEC-Norm: 'int1' und 'int2' werden auf DINT konvertiert. Die Addition wird als DINT-Operation durchgeführt und 'ResultDint1' zugewiesen. *)
ResultDint2 := dint1 + int3; (* 'int3' wird auf DINT konvertiert. Die Addition wird als DINT-Addition durchgeführt. *)
Falls in den Ausdrücken gar kein konkreter Datentyp angeführt ist, wird die Typisierung ebenfalls vom Datentyp der Variable beeinflusst, die das Ergebnis einer überladenen Funktion erhält. Diese Zusatz-Regel ist eine implementierungsabhängige Realisierung, da die IEC-Norm keine Vorgaben dazu enthält.
BeispieleVAR
ResultDintA, ResultDintB, ResultDintC : DINT;
sint1 : SINT := 127;
END_VAR
ResultDintA := 127 + 127; (* Die Addition wird als DINT-Operation durchgeführt, da sonst kein konkreter Datentyp angeführt ist. *)
ResultDintB := 127 + SINT#127; (* 'SINT#127' wird auf DINT konvertiert. Die Addition wird als DINT-Operation durchgeführt und 'ResultDintB' zugewiesen. *)
ResultDintC := 127 + sint1; (* 'sint1' wird auf DINT konvertiert. Die Addition wird als DINT-Operation durchgeführt und 'ResultDintC' zugewiesen.*)
Bei einem →Aufruf, der Eingänge, Ausgänge und/oder einen Ergebniswert mit dem gleichen →allgemeinen Datentyp verwendet, typisiert logi.CAD 3 alle diese Eingänge, Ausgänge und den Ergebniswert des Aufrufs, sogar falls nur eines dieser Elemente mit einem konkreten Datentyp verbunden ist.
BeispieleVAR
Var1, OUT1 : INT;
iForceMrk1 : FORCEMRK;
END_VAR
Var1 := ADD(IN1 := 1, IN2 := 3);
(* Die Eingänge und der Ergebniswert von 'ADD' verwenden den gleichen allgemeinen Datentyp. Da die INT-Variable 'Var1' dem Aufruf von 'ADD' zugewiesen ist (im speziellen: dem Ergebniswert von 'ADD'), wird der Aufruf mit 'INT' typisiert. In Folge werden die Eingänge von 'ADD' ebenfalls mit 'INT' ausgewertet. *)
iForceMrk1(IN := 3, OUT => OUT1);
(* Der Eingang und der Ausgang von 'FORCEMRK' verwenden den gleichen allgemeinen Datentyp. Da der Ausgang 'OUT' von 'iForceMrk1' der INT-Variable 'OUT1' zugewiesen ist, wird der Aufruf mit 'INT' typisiert. In Folge wird der Eingang von 'iForceMrk1' ebenfalls mit 'INT' ausgewertet. *)
Falls ein →anwenderdefinierter Datentyp zur Typisierung verwendet wird, verwendet logi.CAD 3 den →Basistyp. Diese Regel ist von Bedeutung, falls ein →Initialisierungswert im anwenderdefinierten Datentyp definiert ist – in diesem Fall wird nicht der Initialisierungswert des Datentyps verwendet, sondern der Initialisierungswert des Basistyps.
Vergleichen Sie: Bei einem →ARRAY-Datentyp (inkl. einer ARRAY-Deklaration einer Variable) oder einem →strukturiertem Datentyp ist der anwenderdefinierte Datentyp jedoch der Basistyp.BeispieleTYPE
MyInt : INT := 6;
MyStruct : Struct
Elem1 : MyInt;
END_STRUCT;
MyArray : Array [1..1] OF MyInt := [99];
END_TYPE
FUNCTION_BLOCK myFB
VAR
outDerived : MyInt;
outArray1 : MyArray;
outArray2 : Array [1..1] OF MyInt;
outStruct : MyStruct;
iForceMrk1, iForceMrk2, iForceMrk3, iForceMrk4 : FORCEMRK;
END_VAR
iForceMrk1(OUT => outDerived);
(* 'OUT' erhält den Wert '0', da der Initialisierungswert '0' von 'INT' verwendet wird. Hier ist 'INT' der Basistyp. *)
(* Der Initialisierungswert '6' von 'MyInt' wird NICHT verwendet. *)
iForceMrk2(OUT => outArray1);
iForceMrk3(OUT => outArray2);
iForceMrk4(OUT => outStruct);
(* Jedes Element des Ausgangs 'OUT' erhält den Wert '6, da der Initialisierungswert '6' von 'MyINT' verwendet wird. *)
(* Hier ist 'MyINT' der Basistyp jedes Elements des Ausgangs, während 'ARRAY [...] OF' bzw. 'STRUCT' der Basistyp von 'OUT' ist. *)
END_FUNCTION_BLOCK
Falls 2 oder mehrere Aufrufe miteinander verbunden sind, bei denen die verbundenen Eingänge, Ausgänge und/oder der verbundene Ergebniswert von einem allgemeinen Datentyp sind (die anderen jedoch von einem konkreten Datentyp), typisiert logi.CAD 3 alle diese Eingänge, Ausgänge und den Ergebniswert des Aufrufs auf den kleinsten gemeinsamen Datentyp.
Beispiel: Beim PACK-Baustein ist der Ergebniswert vom allgemeinen Datentyp ANY_ELEMENTARY und die Eingänge vom konkreten Datentyp BYTE, beim TO_DINT-Baustein ist der Eingang ebenfalls vom allgemeinen Datentyp ANY_ELEMENTARY und der Ergebniswert vom konkreten Datentyp DINT. Beim folgenden Code wird der Ergebniswert von PACK und der Eingang von TO_DINT mit BOOL typisiert (BOOL ist der kleinster gemeinsame Datentyp von ANY_ALEMENTARY).BeispielVAR
Var1 : DINT;
ByteVar1 : BYTE:= 16#AB;
END_VAR
Var1 := TO_DINT(PACK(ByteVar1, ByteVar1)); (* 'Var1' erhält den Wert '1'. Das ist nicht ein von 'PACK' erwarteter Wert, aber aufgrund der Typisierung das korrekte Ergebnis. *)
Brechen Sie die Verschachtelung auf, um die Typisierung auf den kleinsten gemeinsamen Datentyp zu umgehen.
Abhilfe 1: Erstellen Sie eine Hilfsvariable. Weisen Sie einen Aufruf dieser Hilfsvariable zu. Beim anderen Aufruf wiesen Sie diese Hilfsvariable als Parameter zu.Beispiel für Abhilfe 1VAR
Var1 : DINT;
ByteVar1 : BYTE := 16#AB;
HelperVar : DINT; (* die Hilfsvariable *)
END_VAR
HelperVar := PACK(ByteVar1, ByteVar1);
Var1 := TO_DINT(HelperVar); (* 'Var1' erhält den Wert '43947'. Das ist ein von 'PACK' erwarteter Wert. *)
Abhilfe 2: Erstellen Sie eine benutzerdefinierte POE (z.B. eine Funktion). Weisen Sie einen Aufruf der Bausteine (im folgenden Beispiel: PACK) dem Ergebniswert der Funktion zu. Rufen Sie die Funktion als Parameter des anderen Bausteins (dann: DINT) auf.
Beispiel für Abhilfe 2FUNCTION myFun1 : DWORD
VAR
ByteVar1 : BYTE:= 16#AB;
END_VAR
myFun1 := PACK(ByteVar1, ByteVar1); (* 'PACK' wird dem Ergebnisert der Funktion 'myFun1' zugewiesen. *)
END_FUNCTION
FUNCTION_BLOCK myFB2
VAR
Var1 : DINT;
END_VAR
Var1 := TO_DINT(IN:=myFun1()); (* 'Var1' erhält den Wert '43947'. Das ist ein von 'PACK' erwarteter Wert. *)
END_FUNCTION_BLOCK