REFERENCE
Eine Referenz verweist implizit auf ein anderes Objekt. Beim Zugriff wird die Referenz implizit dereferenziert, und benötigt deswegen keinen speziellen Inhaltsoperator ^ wie ein Pointer.
Syntax
<identifier> : REFERENCE TO <data type> ;
<data type> : base type of the reference
Beispieldeklaration:
PROGRAM_MAIN
VAR
refInt : REFERENCE TO INT;
nA : INT;
nB : INT;
END_VAR
Sie können nun refInt als „Alias“ für Variablen des Typs INT verwenden.
Zuweisung:
Die Adresse der Referenz müssen Sie über eine separate Zuweisungsoperation mit Hilfe des Zuweisungsoperators REF= setzen. Eine Ausnahme hiervon besteht, wenn ein Input ein REFERENCE TO ist und der Input innerhalb des Aufrufs übergeben wird. Dann wird anstelle des Zuweisungsoperators REF= der normale Zuweisungsoperator := verwendet.
FUNCTION_BLOCK FB_Sample
VAR_INPUT
refInput1 : REFERENCE TO INT;
refInput2 : REFERENCE TO INT;
END_VAR
PROGRAM MAIN
VAR
fbSample : FB_Sample;
n1 : INT;
n2 : INT;
END_VAR
fbSample.refInput1 REF= n1;
fbSample(refInput2 := n2);
Ob eine Referenz auf einen gültigen Wert (zum Beispiel ungleich 0) zeigt, können Sie mithilfe eines speziellen Operators überprüfen (siehe Referenzen auf Gültigkeit prüfen).
Anwendungsbeispiel:
refInt REF= nA; // refInt points now to nA
refInt := 12; // nA has got the value 12
nB := refInt * 2; // nB has got the value 24
refInt REF= nB; // refInt points now to nB
refInt := nA / 2; // nB has got the value 6
refInt REF= 0; // explicit initialisation of the reference
TwinCAT initialisiert Referenzen (mit 0). |
Zuweisungsoperator REF=
Der Operator erzeugt eine Referenz (Pointer) auf einen Wert.
Syntax:
<variable name> REF= <variable name>
Beispiel:
PROGRAM MAIN
VAR
refA : REFERENCE TO ST_Sample;
stA : ST_Sample;
refB : REFERENCE TO ST_Sample;
stB1 : ST_Sample;
stB2 : ST_Sample;
END_VAR
refA REF= stA; // represents => refA := ADR(stA);
refB REF= stB1; // represents => refB := ADR(stB1);
refA := refB; // represents => refA^ := refB^; (value assignment of refB as refA and refB are implicitly dereferenced)
refB := stB2; // represents => refB^ := stB2; (value assignment of stB2 as refB is implicitly dereferenced)
END_VAR
Ungültige Deklarationen
PROGRAM MAIN
VAR
aTest : ARRAY[0..9] OF REFERENCE TO INT;
pTest : POINTER TO REFERENCE TO INT;
refTestRef : REFERENCE TO REFERENCE TO INT;
refTestBit : REFERENCE TO BIT;
END_VAR
Ein Referenztyp darf nicht als Basistyp eines Arrays, Pointers oder einer Referenz verwendet werden. Außerdem darf eine Referenz nicht auf eine Bit-Variable verweisen. Solche Konstrukte erzeugen Compilerfehler.
Vergleich von Referenz und Pointer
Eine Referenz hat gegenüber einem Pointer folgende Vorteile:
- Einfachere Nutzung:
- Eine Referenz kann direkt, ohne Dereferenzierung auf die Inhalte des referenzierten Objekts zugreifen.
- Schönere und einfachere Syntax bei Übergabe von Werten:
- Aufruf eines Funktionsbausteins, der statt einem Pointer eine Referenz ohne Adressoperator übergibt.
- Beispiel:
FB_Test1(refInput := nValue);
statt:FB_Test2(pInput := ADR(nValue));
- Typsicherheit:
- Der Compiler prüft bei der Zuweisung zweier Referenzen, ob deren Basistypen übereinstimmen. Bei Pointern wird dies nicht geprüft.
Referenzen auf Gültigkeit prüfen
Sie können den Operator __ISVALIDREF
verwenden, um zu prüfen, ob eine Referenz auf einen gültigen Wert weist, das heißt auf einen Wert ungleich 0.
Syntax:
<boolesche Variable> := __ISVALIDREF(<mit REFERENCE TO <datatype> deklarierter Kennzeichner>);
Die boolesche Variable wird TRUE, wenn die Referenz auf einen gültigen Wert zeigt, andernfalls FALSE.
Beispiel
PROGRAM_MAIN
VAR
nVar : INT;
refInt1 : REFERENCE TO INT;
refInt2 : REFERENCE TO INT;
bTestRef1 : BOOL := FALSE;
bTestRef2 : BOOL := FALSE;
END_VAR
nVar := nVar + 1;
refInt1 REF= nVar;
refInt2 REF= 0;
bTestRef1 := __ISVALIDREF(refInt1); (* becomes TRUE, because refInt1 points to nVar, which is non-zero *)
bTestRef2 := __ISVALIDREF(refInt2); (* becomes FALSE, because refInt2 is set to 0 *)
Die implizite Überwachungsfunktion Checkpointer wirkt auch auf Variablen vom Typ |
Automatische Zeiger-/Referenzaktualisierung beim Online-Change
Verfügbar ab TwinCAT 3.1 Build 4026 |
Die nachfolgenden Beschreibungen beziehen sich sowohl auf Zeiger als auch auf Referenzen. Für eine vereinfachte Lesbarkeit wird im Folgenden jedoch nur der Begriff des Zeigers verwendet.
Funktion:
Bei einem Online-Change werden die Werte aller SPS-Zeiger automatisch aktualisiert, sodass der jeweilige Zeiger auf die gleiche Variable bzw. auf das gleiche Objekt verweist wie vor dem Online-Change. Dadurch behält ein Zeiger nach dem Online-Change seine Gültigkeit, auch wenn die Variable, auf die gezeigt wird, während des Online-Changes an eine andere Speicherposition verschoben wird.
Funktionsweise:
Bei einem Online-Change wird für jeden Zeiger geprüft, ob dieser auf ein SPS-Symbol verweist. Für eine solche Ermittlung müssen die u. g. Voraussetzungen erfüllt sein.
- Fall 1: Symbol wurde ermittelt
- Wenn das Symbol in den neuen Symbolen, die nach dem Online-Change existieren, noch besteht und wenn sich der Typ des Symbols nicht geändert hat, wird der Zeiger auf das gefundene Symbol umgesetzt. Der Zeiger- bzw. der Adresswert wird aktualisiert.
- Wenn das Symbol in den neuen Symbolen nicht mehr existiert oder wenn sich der Typ des Symbols geändert hat, wird der Zeiger auf null gesetzt.
- Fall 2: Symbol wurde nicht ermittelt
- Wenn ein Zeiger auf eine Adresse verweist, für die auch vor dem Online-Change kein Symbol gefunden wird (z. B. weil der Pointer in einen Speicherbereich außerhalb der SPS zeigt), wird der Zeigerwert beim Online-Change nicht verändert.
Voraussetzungen:
- Für diese Funktion wird die (ADS-) Symbolbeschreibung der Variablen benötigt, auf die der Zeiger verweist. Liegt für eine Variable keine Symbolbeschreibung vor, z. B. aufgrund der Verwendung von Attribut 'hide', wird der Zeiger nicht berücksichtigt.
- Der Zeiger muss auf eine Variable/ein Objekt innerhalb des SPS-Speichers verweisen. Zeiger, die auf einen Speicherbereich außerhalb des SPS-Speichers verweisen, werden beim Online-Change nicht verändert.
Zusätzliche Aktualisierungsmöglichkeit:
Die beschriebene Funktionalität steht ab TwinCAT 3.1 Build 4026 zur Verfügung. Ein ggf. bisheriger, manuell implementierter Mechanismus zur Aktualisierung eines Zeigers kann weiterhin verwendet werden. Hierbei kann dem Zeiger z. B. zyklisch das gewünschte Ziel zugewiesen werden. Es besteht keine Notwendigkeit, diese Codezeilen aus dem Projekt zu entfernen. Gleichermaßen ist es nicht erforderlich, diese Codezeilen zu behalten bzw. zu implementieren.
Siehe auch: