Skip to main content

Bedingte Pragmas

Einschränkung bei bedingten Pragmas

Verwenden Sie Pragmas für bedingte Kompilierung nur in Implementierungen von Programmierbausteinen. In Deklarationen werden diese Pragmas nicht ausgewertet sondern ignoriert.

Beachten Sie bitte die folgende Ausnahme: Das IF-Pragma mit dem Operator project_defined kann in Deklarationen eingefügt werden. Für weitere Informationen siehe: IF-Pragma mit project_defined (<global define>)

Die Pragmas werden vom Compiler beim Vorübersetzungsprozess und beim Übersetzungsprozess ausgewertet. Dieser Vorgang nennt sich bedingte Kompilierung. Die Implementierungssprache ST unterstützt diese Pragmas.

Die Pragmas {IF <expression> } zusammen mit {ELSIF <expression> }, {ELSE} und dem abschließenden {END_IF} kennzeichnen in Implementierungen Code, der abhängig von den angegebenen Bedingungen beibehalten oder ignoriert wird. Die angegebenen Bedingungen in <expression> sind ganzzahlige konstante Ausdrücke, die aus verschiedenen Operanden und Operatoren zusammengesetzt sein können.

Beim Kompilieren wird als erstes der Ausdruck in <{IF <expression>} ausgewertet. Wenn dessen Rückgabewert FALSE ist, wird in den nächsten {ELSIF <expression>}-Abschnitt verzweigt und der dortige Ausdruck ausgewertet, solange bis ein Abschnitt einen Ausdruck mit TRUE liefert. Die Ausdrücke werden somit sukzessive ausgewertet, bis einer einen Wert ungleich 0 liefert. Nur dieser eine mit einem positiven Ausdruck verknüpfte Codeabschnitt wird kompiliert. Die anderen werden ignoriert. Wenn alle Ausdrücke 0 liefern, wird nach {ELSE} verzweigt. Wenn das {ELSE}-Pragma fehlt, kann der Fall eintreten, dass kein Codeabschnitt kompiliert wird.

Syntax

Beispiel Codefragment

Beschreibung

{IF <expression> }

{IF defined (DEF0815)}
{info 'DEF0815 has been defined'}
Cnt0815 := iCnt0815 + 1;

Kennzeichnet den Anfang des Codeabschnitts, der bei einer gültiger Bedingung <expression> kompiliert wird

{ELSIF <expression> }

{ELSIF defined (DEF0816)}
{info 'DEF0815 has been defined'}
iCnt0816 := iCnt0816 + 1;

Keinmal, einmal oder mehrmals

Abzweig, der den alternativen Codeabschnitt bei einer gültiger Bedingung <expression> kennzeichnet

{ELSE}

{ELSE}
{info 'DEF0815 not defined'}
iCnt0 := iCnt0 - 1;

Optional

Abzweig, der den Codeabschnitt kennzeichnet, der kompiliert wird, wenn die vorherigen Bedingungen nicht eintreten

{END_IF}

{END_IF}

Kennzeichnet das Ende des bedingten Codeabschnitts

<expression>

defined (DEF0815)

Bedingung

Ganzzahliger, zur Kompilierungszeit konstanter Ausdruck, der aus Operatoren und Operanden, wie beispielsweise Compiler-Defines, Variablen oder Literale, zusammengesetzt sein kann

Compiler-Define

Compiler-Defines werden als Kennzeichen für bestimmte Zustände im Code verwendet. Ein Compiler-Define kann gesetzt, gelöscht oder mit Hilfe der defined-Operatoren geprüft werden.

Syntax

Beispiel

Beschreibung

{define <name> }

{define DEF0815}

Definiert das Compiler-Define <name> mit Typ BOOL

Anmerkung

Das Compiler-Define <name> unterliegt den Regeln für gültige Bezeichner.

{define <name> <string> }

{define DEF0123 '123'}

Definiert das Compiler-Define <name> und weist als Wert das Stringliteral <string> zu

{undefine <name>}

{undefine DEF0815}

Hebt das Compiler-Define <name> auf

Der Bezeichner ist danach undefiniert. Ein Pragma mit einem undefinierten Compiler-Define wird ignoriert.

Tipp

Alternativ können Sie Ausdrücke und Compiler-Defines lokal in den Eigenschaften einer POU oder applikationsweit in den Eigenschaften der übergeordneten Applikation definieren.

Selektieren Sie dafür die POU oder die übergeordnete Applikation im Gerätebaum. Wählen Sie in deren Kontextmenü Eigenschaften und dann die Registerkarte Build. Dort im Eingabefeld Compiler-Defines können Sie ein Literal oder einen Ausdruck definieren, beispielsweise DEF0815. Das Eingabefeld erwartet keine Pragmaanweisung wie {define }, sondern lediglich einen Namen.

Sie können mehrere Compiler-Defines durch Komma getrennt angeben.

Operatoren

defined (variable: <variable name> )

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn die Variable <variable name> innerhalb des aktuellen Gültigkeitsbereichs deklariert ist; ansonsten wird FALSE geliefert.

Beispiel 293. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Die Variable g_bTest ist in App1 deklariert, nicht aber in App2.

{IF defined (variable: g_bTest)}
    (* the following code is only processed in App2*)
    g_bTest := x > 300;
{END_IF}


defined (<identifier>)

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält. Voraussetzung ist, dass der Bezeichner <identifier> mit Hilfe einer {define}-Anweisung definiert wurde und danach nicht mit einer {undefine}-Anweisung wieder undefiniert wurde; ansonsten wird FALSE geliefert.

Voraussetzung: Es gibt die Applikationen App1 und App2. Die Variable pdef1 ist durch eine {define}-Anweisung in App1 definiert, nicht aber in App2.

{IF defined (pdef1)}
(* This code is processed in App1 *)
{info 'pdef1 defined'}
    hugo := hugo + SINT#1;
{ELSE}
(* the following code is only processed in App2 *)
{info 'pdef1 not defined'}
    hugo := hugo - SINT#1;
{END_IF}

Hier ist zusätzlich ein Beispiel eines Meldungspragmas enthalten: Nur die Meldung pdef1 defined wird im Meldungsfenster angezeigt, wenn die Applikation kompiliert wird, weil pdef1 tatsächlich definiert ist. Die Meldung pdef1 not defined wird ausgegeben, wenn pdef1 nicht definiert ist

defined (type: <identifier> )

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn ein Datentyp mit dem Bezeichner <identifier> deklariert ist; ansonsten wird FALSE geliefert.

Beispiel 294. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Datentyp DUT ist in App1 deklariert, nicht aber in App2.

{IF defined (type: DUT)}
    (* the following code is only processed in App1*)
    bDutDefined := TRUE;
{END_IF}


defined (pou: <pou name>)

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn eines der folgenden Objekte mit dem Namen <pou-name> vorhanden ist:

  • Funktionsbaustein

  • Funktion

  • Programm

  • Aktion

  • Methode

  • Schnittstelle

Ansonsten wird FALSE geliefert.

Beispiel 295. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Der Baustein CheckBounds ist in App1 vorhanden, nicht aber in App2.

{IF defined (pou: CheckBounds)}
    (* the following code is only processed in App1 *)
    arrTest[CheckBounds(0,i,10)] := arrTest[CheckBounds(0,i,10)] + 1;
{ELSE}
    (* the following code is only processed in App2 *)
    arrTest[i] := arrTest[i]+1;
{END_IF}


defined (resource: <identifier>)

Wichtig

Noch nicht implementiert

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn ein Ressourcen-Objekt mit dem Namen <identifier> für die Applikation vorhanden ist; ansonsten wird FALSE geliefert.

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Ein Ressourcen-Objekt glob_var1 der Globalen Variablenliste ist für App1 vorhanden, nicht aber für App2.

{IF defined (resource:glob_var1)}
    (* the following code is only processed in App1 *)
    gvar_x := gvar_x + ivar;
{ELSE}
    (* the following code is only processed in App2 *)
    x := x + ivar;
{END_IF}

defined (task: <task name> )

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn eine Task mit dem Namen <task name> definiert ist; ansonsten wird FALSE geliefert.

Syntax

{ IF defined (task: <task name> }
{ ELSIF defined (task: <task name> }
Beispiel 296. Beispiel
{IF defined (task: Task_D)}


Beispiel 297. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Task PLC_PRG_Task ist in App1 definiert, nicht aber in App2.

{IF defined (task: PLC_PRG_Task)}
    (* the following code is only processed in App1 *)
    erg := plc_prg.x;
{ELSE}
    (* the following code is only processed in App2 *)
    erg := prog.x;
{END_IF}


defined (IsLittleEndian)

Der Operator bewirkt, dass der Ausdruck den Wert FALSE erhält, wenn der Speicher der CPU in Big-Endian (Motorola Byte Order) organisiert ist.

defined (IsSimulationMode)

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn die Applikation auf einem simulierten Gerät läuft, also im Simulationsbetrieb ist.ei

Weitere Informationen finden Sie unter Testen im Simulationsbetrieb.

defined (IsFPUSupported)

Wenn der Ausdruck den Wert TRUE liefert, erzeugt der Codegenerator bei der Berechnungen mit REAL-Werten einen FPU-Code (für den Floating Point Unit-Porzessor). Ansonsten werden die FPU-Operationen emuliert, was jedoch bedeutend langsamer ist.

hasattribute (pou: <pou name>, ' <attribute name> ')

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn das Attribut <attribute name> in der ersten Zeile des Deklarationsteils des Bausteins <pou name> angegeben ist; ansonsten wird FALSE zurückgeliefert.

Beispiel 298. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Die Funktion fun1 ist in App1 und App2 deklariert, aber in App1 ist sie zusätzlich mit dem Pragma {attribute 'vision'} versehen.

In App1:

{attribute 'vision'}
FUNCTION fun1 : INT
VAR_INPUT
    i : INT;
END_VAR
VAR
END_VAR

In App2:

FUNCTION fun1 : INT
VAR_INPUT
    i : INT;
END_VAR
VAR
END_VAR

Pragmaanweisung:

{IF hasattribute (pou: fun1, 'vision')}
    (* the following code is only processed in App1 *)
    ergvar := fun1(ivar);
{END_IF}


hasattribute (variable: <variable name> , ' <attribute name> ')

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn der Variablen das Pragma {attribute '<attribute name>'} in der Zeile vor der Variablendeklaration zugewiesen ist; ansonsten wird FALSE zurückgeliefert.

Beispiel 299. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Die Variable g_globalInt wird in App1 und App2 verwendet, aber in App1 ist ihr zusätzlich das Attribut 'DoCount' zugewiesen.

Deklaration g_GlobalInt in App1

VAR_GLOBAL
    {attribute 'DoCount'}
    g_globalInt : INT;
    g_multiType : STRING;
END_VAR

Deklaration g_GlobalInt in App2:

VAR_GLOBAL
    g_globalInt : INT;
    g_multiType : STRING;
END_VAR

Pragmaanweisung:

{IF hasattribute (variable: g_globalInt, 'DoCount')}
    (* the following code is only processed in App1 *)
    g_globalInt := g_globalInt + 1;
{END_IF}


hasconstanttype( <constant name> , <boolean literal> )

Der Operator prüft, ob die mit <constant name> bezeichnete Konstante ersetzt oder nicht ersetzt wurde. Auf was geprüft wird, wird mit dem zweiten Parameter (Boolescher Wert) gesteuert:

  • TRUE: Prüft, ob Konstante ersetzt wurde

  • FALSE: Prüft, ob Konstante nicht ersetzt wurde

Wenn der jeweilige Fall eintritt, liefert der Operator TRUE zurück.

Syntax

{ IF hasconstanttype( <constant namne> , <boolean literal> ) }

{ ELSIF hasconstanttype( <constant namne> , <boolean literal> ) }

Beispiel 300. Beispiel
 {IF hasconstanttype(PLC_PRG.aConst, TRUE)}


. Das automatische Ersetzen von Konstanten hängt prinzipiell von Folgendem ab:
  • Compile-Option Konstanten ersetzen

  • Konstantentyp (beispielsweise werden STRING-Typen nie ersetzt)

  • Verwendung des Attributs {attribute 'const_non_replaced'}

  • Verwendung des Attributs {attribute 'const_replaced'}

Beispiel 301. Beispiel
VAR
    iCntMAXIsReplaced: INT;
    xErrorOccured : BOOL;
END_VAR
VAR CONSTANT
    c_iMAX: INT := 99;
END_VAR

{IF hasconstanttype(c_iMAX, TRUE)}
    iCntMAXIsReplaced := iCntMAXIsReplaced + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}


hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

Der Operator vergleicht den Wert der mit <constant name> bezeichneten Konstante mit dem Wert des zweiten Parameters. Der zweite Parameter kann entweder als Literal <literal> oder als Variable <variable name> angegeben werden.

. Vergleichsoperatoren <comparison operator>:
  • größer (>)

  • größer oder gleich (>=)

  • gleich (=)

  • ungleich (<>)

  • kleiner oder gleich (<=)

  • kleiner (<)

Syntax

{ IF hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

{ IF hasconstantvalue( <constant name> , <literal> , <comparison operator> )

{ ELSIF hasconstantvalue( <constant name> , <variable name> , <comparison operator> )

{ ELSIF hasconstantvalue( <constant name> , <literal> , <comparison operator> )

Beispiel 302. Beispiel
{IF hasconstantvalue(PLC_PRG.aConst, 99, >)}
{ELSIF hasconstantvalue(PLC_PRG.aConst, GVL.intconst99, =)}


Beispiel 303. Beispiel
PROGRAM PRG_ConditionConstantValue
VAR
    iCntMAX: INT;
    iCntGlobalMAX : INT;
    iCntABC: INT;
    iCntGlobalABC : INT;
    xErrorOccured : BOOL;
END_VAR
VAR CONSTANT
    c_iMAX: INT := 999;
    c_sABC: STRING := 'ABC';
    {attribute 'const_non_replaced'}
    c_iNonReplaceable: INT := 888;
END_VAR

{IF hasconstantvalue(c_iMAX, 999, =)}
    iCntMAX := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}

{IF hasconstantvalue(c_iMAX, GVL.gc_iMAX, =)}
    iCntGlobalMAX := iCntGlobalMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}

{IF hasconstantvalue(c_sABC, 'ABC', =)}
    iCntABC := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}
{IF hasconstantvalue(c_sABC, GVL.gc_sABC, =)}
    iCntGlobalABC := iCntMAX + 1;
{ELSE}
    xErrorOccured := FALSE;
{END_IF}


hastype (variable: <variable name>, <data type> )

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn die Variable <variable> vom Datentyp <type-spec> ist; ansonsten wird FALSE zurückgeliefert.

Mögliche Datentypen <data type>:

BOOL | BYTE | DATE | DATE_AND_TIME | DT | DINT | DWORD | INT | LDATE | LDATE_AND_TIME | LDT | LINT | LREAL | LTIME | LTIME_OF_DAY | LTOD | LWORD | REAL | SINT | STRING | TIME | TIME_OF_DAY | TOD | ULINT | UDINT | UINT | USINT | WORD | WSTRING

Beispiel 304. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Die Variable g_multitype ist in App1 mit Datentyp LREAL deklariert, in App2 mit Datentyp STRING.

{IF (hastype (variable: g_multitype, LREAL))}
    (*  the following code is only processed in App1 *)
    g_multitype := (0.9 + g_multitype) * 1.1;
{ELSIF (hastype (variable: g_multitype, STRING))}
    (* the following code is only processed in App2 *)
    g_multitype := 'this is a multitalent';
{END_IF}


hasvalue (PackMode, ' <pack mode value> ')

Der abgeprüfte PackMode hängt von der Gerätebeschreibung ab, nicht vom Pragma, das für einzelne DUTs angegeben werden kann.

hasvalue (RegisterSize, ' <register size> ')

<register size>: Größe eines CPU-Registers in Bit

Der Operator bewirkt, dass der Ausdruck den Wert TRUE liefert, wenn die Größe eines CPU-Registers gleich <register size> ist.

Mögliche Werte für <register size>

  • 16 für C16x,

  • 64 für X86-64 Bit

  • 32 für X86-32 Bit

hasvalue (<define-ident>, ' <character string> ')

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn eine Variable mit Bezeichner <define-ident> definiert ist und den Wert <character string> hat; ansonsten wird  FALSE zurückgeliefert.

Beispiel 305. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Variable test wird in den Applikationen App1 und App2 verwendet; in App1 erhält sie den Wert 1, in App2 den Wert  2.

{IF hasvalue(test,'1')}
    (*  the following code is only processed in App1 *)
    x := x + 1;
{ELSIF hasvalue(test,'2')}
    (*  the following code is only processed in App2 *)
        x := x + 2;
{END_IF}


project_defined (<global define>)

Dieser Operator steht ab CODESYS V3.5 SP20 zur Verfügung.

Der Operator bewirkt, dass der Ausdruck den Wert TRUE erhält, wenn das globale Define <global define> in der Liste der globalen Defines in den Compile-Optionen der Projekteinstellungen enthalten ist.

Der Operator wird als Bedingung einer IF-Anweisung angegeben und kann sowohl in der Implementierung als auch im Deklarationsteil von ST-POUs und von Bibliotheken verwendet werden. Sie können mithilfe der Operatoren AND und OR mit anderen Defines kombiniert werden, wenn diese an der jeweiligen Position erlaubt sind.

Im Deklarationsteil von POUs können IF-Anweisungen mit dem Operator project_defined (<global define>) folgende Konstrukte enthalten:

  • Variablendeklarationen

    Beispiel:

    {If project_defined(define1)}
        x : DINT;
    {END_IF}
  • Kommentierungen

  • Attribut-Deklarationen

  • Pragma-Anweisungen

Folgende Konstrukte sind nicht möglich:

  • Komplette Variablendeklarationen

    Beispiel

    {If project_defined(define1)}
    VAR
        x : DINT;
    END_VAR
    {END_IF}
  • Komplette Deklarationen von POUS

    Beispiel:

    {If project_defined(define1)}
    FUNCTION POU : BOOL
    VAR_INPUT
        x : INT;
    END_VAR
    {END_IF}
  • Gültigkeitsbereiche: VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT

NOT <operator>

Der Ausdruck erhält den Wert TRUE, wenn der Umkehrwert von <operator> den Wert TRUE liefert. <operator> kann einer der in diesem Kapitel beschriebenen Operatoren sein.

Beispiel 306. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. PLC_PRG1 ist in App1 und App2 vorhanden, die POU CheckBounds gibt es nur in App1.

{IF defined (pou: PLC_PRG1) AND NOT (defined (pou: CheckBounds))}
    (* the following code is only processed in App2 *)
    bANDNotTest := TRUE;
{END_IF}


<operator> AND <operator>

Der Ausdruck erhält den Wert TRUE, wenn die beiden angegebenen Operatoren TRUE liefern. <operator> kann einer der in diesem Kapitel beschriebenen Operatoren sein.

Beispiel 307. Beispiel

Voraussetzung: Es gibt die Applikationen App1 und App2. PLC_PRG1 ist in App1 und App2 vorhanden, die POU CheckBounds nur in App1.

{IF defined (pou: PLC_PRG1) AND (defined (pou: CheckBounds))}
    (* the following code is only processed in App1 *)
    bANDTest := TRUE;
{END_IF}


<operator> OR <operator>

Der Ausdruck liefert TRUE, wenn einer der beiden angegebenen Operatoren TRUE liefert. <operator> kann einer der hier beschriebenen Operatoren sein.

Beispiel 308. Beispiel

Voraussetzung: Es gibt zwei Applikationen App1 und App2. Die POU PLC_PRG1 ist in App1 und App2 vorhanden, die POU CheckBounds nur in App1.

{IF defined (pou: PLC_PRG1) OR (defined (pou: CheckBounds))}
    (* the following code is only processed in App1 and in App2 *)
    bORTest := TRUE;
{END_IF}


(<operator>)

() klammert die Operatoren.