Verschattungsregeln
In CODESYS ist es prinzipiell erlaubt, den gleichen Bezeichner für verschiedene Elemente zu verwenden. So können beispielsweise ein Baustein und eine Variable gleich benannt werden. Um Verwechslungen vorzubeugen, sollte dies jedoch vermieden werden.
Negativbeispiel: Im folgenden Codeausschnitt hat eine lokale Funktionsbaustein-Instanz den gleichen Namen wie eine Funktion:
In einem solchen Fall ist unklar, ob im Programm die Instanz oder die Funktion aufgerufen wird.
FUNCTION YYY : INT ; END_FUNCTION FUNCTION_BLOCK XXX ; END_FUNCTION_BLOCK PROGRAM PLC_PRG VAR YYY : XXX; END_VAR YYY(); END_PROGRAM
Compilerverhalten bei Verschattung
Der Compiler meldet grundsätzlich weder Fehler noch Warnungen, wenn derselbe Bezeichner für verschiedene Elemente verwendet wird. Stattdessen durchsucht der Compiler den Code in einer bestimmten Reihenfolge nach der Deklaration des Bezeichners. Wenn eine Deklaration gefunden wurde, dann sucht der Compiler nicht nach eventuellen weiteren Deklarationen an anderer Stelle. Wenn weitere Deklarationen existieren, dann sind diese für den Compiler „verschattet“. Im Folgenden werden die Verschattungsregeln beschrieben, das heißt die Suchreihenfolgen, die der Compiler bei der Suche nach der Deklaration für Bezeichner verwendet. Im Abschnitt „Uneindeutige Zugriffe und qualifizierte Zugriffe“ werden Möglichkeiten aufgezeigt, um uneindeutige Zugriffe zu vermeiden und die Verschattungsregeln zu umgehen.
Verschattung vermeiden
Um sicherzustellen, dass Namen immer eindeutig sind, sollten Namenskonventionen beachtet werden, beispielsweise bestimmte Präfixe für Variablen.
Für weitere Informationen siehe: Bezeichnervergabe
Namenskonventionen können mit Hilfe der statischen Codeanalyse von CODESYS automatisch überprüft werden. Die statische Codeanalyse könnte auch die doppelte Verwendung des Namens YYY
aufdecken und als Fehler melden.
Auch durch die konsequente Verwendung des Attributs qualified_only
für Enumerationen und globale Variablenlisten und durch die Verwendung von qualifizierten Bibliotheken können nicht-eindeutige Situationen vermieden werden.
Um sicherzustellen, dass beim Aufruf eines Programmierbausteins der Ansicht POUs nicht ein gleichnamiger Programmierbaustein der Ansicht Geräte aufgerufen wird, sollte beim Aufruf dem Namen des Programmierbausteins der Operator __POOL
vorangestellt werden.
Beispiel: svar_pou := __POOL.POU();
Suchreihenfolge in der Applikation
Wenn der Compiler im Code einer Applikation auf einen einzelnen Bezeichner trifft, dann sucht er die zugehörige Deklaration in der folgenden Reihenfolge:
Lokale Variablen
Lokale Variablen einer Methode
Lokale Variablen im Funktionsbaustein, Programm oder Funktion und in eventuellen Basisfunktionsbausteinen
Lokale Methoden des Bausteins
Globale Variablen
Globale Variablen in der Applikation, wenn in der Variablenliste, in der die globalen Variablen deklariert sind, nicht das Attribut
qualified_only
gesetzt istGlobale Variablen in einer Vaterapplikation, sofern in der Variablenliste, in der die globalen Variablen deklariert sind, nicht das Attribut
qualified_only
gesetzt istGlobale Variablen in angezogenen Bibliotheken, wenn weder die Bibliothek noch die Variablenliste qualifizierten Zugriff erfordert
Baustein- oder Typnamen
Baustein- oder Typnamen aus der Applikation (das heißt: Namen von Globalen Variablenlisten, Funktionsbausteinen, etc.)
Baustein- oder Typnamen aus einer Vaterapplikation
Baustein- oder Typnamen aus einer Bibliothek
Bibliotheken
Namensräume von lokal angezogenen Bibliotheken und Bibliotheken, die von Bibliotheken veröffentlicht werden
Ansicht POUs
Globale Variablen in der Ansicht POUs, sofern in der Variablenliste, in der sie deklariert sind, nicht das Attribut
qualified_only
gesetzt istBaustein- oder Typnamen aus der Ansicht POUs (das heißt: Namen von Globalen Variablenlisten, Funktionsbausteinen, etc.)
Bibliotheken aus POUs
Tipp
Bibliotheken, die im Bibliotheksverwalter der Ansicht POUs eingefügt werden, werden mit der entsprechenden Platzhalterauflösung in den Bibliotheksverwalter in allen Applikationen im Projekt gespiegelt. Diese Bibliotheken bilden dann mit den Bibliotheken in der Applikation einen gemeinsamen Namensraum. Daher gibt es keine Verschattung von Bibliotheken im Pool durch Bibliotheken in der Applikation.
Suchreihenfolge in der Bibliothek
Wenn der Compiler im Code einer Bibliothek auf einen einzelnen Bezeichner trifft, dann sucht er die zugehörige Deklaration in der folgenden Reihenfolge:
Lokale Variablen
Lokale Variablen einer Methode
Lokale Variablen im Funktionsbaustein, Programm oder Funktion und in eventuellen Basis-Funktionsbausteinen
Lokale Methoden des Bausteins
Globale Variablen
Globale Variablen in der lokalen Bibliothek, wenn die Variablenliste, in der die globalen Variablen deklariert sind, nicht das Attribut
qualified_only
gesetzt hatGlobale Variablen in angezogenen Bibliotheken, wenn weder die Bibliothek noch die Variablenliste qualifizierten Zugriff erfordert
Bibliotheken
Baustein- oder Typnamen aus der lokalen Bibliothek (das heißt: Namen von globalen Variablenlisten, Funktionsbausteinen, etc.)
Baustein- oder Typnamen aus einer angezogenen Bibliothek
Namensräume von lokal angezogenen Bibliotheken und Bibliotheken, die von lokal angezogenen Bibliotheken veröffentlicht werden
Uneindeutige Zugriffe und qualifizierte Zugriffe
Trotz dieser Suchreihenfolgen kann es zu uneindeutigen Zugriffen kommen. Das ist zum Beispiel der Fall, wenn eine Variable mit dem gleichen Namen in zwei globalen Variablenlisten vorkommt, die nicht qualifizierten Zugriff erfordern. Einen solchen Fall meldet der Compiler als Fehler (zum Beispiel: Nicht eindeutige Verwendung des Namens XXX).
Eine solche uneindeutige Verwendung lässt sich durch einen qualifizierten Zugriff, also beispielsweise durch den Zugriff über den Namen der globalen Variablenliste, eindeutig machen (zum Beispiel: GVL.XXX
).
Ein qualifizierter Zugriff lässt sich auch immer dazu nutzen, um Verschattungsregeln zu umgehen.
Mit dem Namen der globalen Variablenliste kann eindeutig auf eine Variable in dieser Liste zugegriffen werden.
Mit dem Namen einer Bibliothek kann eindeutig auf Elemente in dieser Bibliothek zugegriffen werden.
Mit dem Pointer
THIS
kann eindeutig auf Variablen in einem Funktionsbaustein zugegriffen werden, auch wenn eine lokale Variable mit gleichem Namen in einer Methode des Funktionsbausteins existiert.
Um jederzeit die Deklarationsstelle eines Bezeichners zu finden, wählen Sie den Befehl
. Dies kann insbesondere dann hilfreich sein, wenn der Compiler eine scheinbar unverständliche Fehlermeldung produziert.Suchen in Instanzpfaden
Die oben beschriebenen Suchreihenfolgen gelten nicht für Bezeichner, die in einem Instanzpfad als Komponente auftauchen, oder für Bezeichner, die als Eingänge in Aufrufen verwendet werden.
Für einen Zugriff der folgenden Art yy.component
hängt es von der Entität ab, die durch yy
beschrieben wird, wo nach der Deklaration von component
gesucht wird.
Wenn yy
eine Variable mit strukturiertem Datentyp bezeichnet (also vom Typ STRUCT
oder UNION
), dann wird component
in dieser Reihenfolge gesucht:
Lokale Variablen des Funktionsbausteins
Lokale Variablen des Basis-Funktionsbausteins
Methoden des Funktionsbausteins
Methoden des Basis-Funktionsbausteins
Wenn yy
eine globale Variablenliste bezeichnet oder ein Programm, dann wird component
nur in dieser Liste gesucht.
Wenn yy
einen Namensraum einer Bibliothek bezeichnet, dann wird component
in dieser Bibliothek genau so gesucht, wie es im obigen Abschnitt „Suchreihenfolge in der Bibliothek“ beschrieben ist.
Erst in zweiter Instanz entscheidet der Compiler, ob der Zugriff auf das gefundene Element erlaubt ist, das heißt, ob die Variable möglicherweise nur lokal zugreifbar ist, oder ob eine Methode privat ist. Wenn der Zugriff nicht erlaubt ist, dann wird ein Fehler ausgegeben.