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. einerARRAY
-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: BeimPACK
-Baustein ist der Ergebniswert vom allgemeinen DatentypANY_ELEMENTARY
und die Eingänge vom konkreten DatentypBYTE
, beimTO_DINT
-Baustein ist der Eingang ebenfalls vom allgemeinen DatentypANY_ELEMENTARY
und der Ergebniswert vom konkreten DatentypDINT
. Beim folgenden Code wird der Ergebniswert vonPACK
und der Eingang vonTO_DINT
mitBOOL
typisiert (BOOL
ist der kleinster gemeinsame Datentyp vonANY_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