Bit Access

Bit access selects a single bit of an integer-typed or bit-string-typed variable. The selected bit reads and writes as a BOOL. The Edition 3 partial-access syntax generalizes this to also select a byte, word, double word, or long word of a wider value.

IEC 61131-3

Section 2.4.1.2 (partial access)

Support

Supported (.n short form); Edition 3 (.%Xn, .%Bn, .%Wn, .%Dn, .%Ln)

Syntax

IronPLC accepts two equivalent forms for bit access:

Form

Example

Availability

variable.n

my_byte.3

Always supported (Edition 2 short form)

variable.%Xn

my_byte.%X3

Edition 3 partial-access syntax; see below

Both forms denote the same bit and produce the same runtime behavior — they differ only in surface syntax. Bit indices are zero-based, with 0 being the least significant bit.

Bit access composes with other variable references. The bit suffix may follow any symbolic variable, including array subscripts and structure field accesses:

my_byte.3              (* simple variable *)
my_array[i].3          (* array element *)
my_record.field.3      (* structure field *)

Valid Base Types

Bit access is valid on any integer or bit-string type:

Type family

Types

Valid bit indices

8-bit

SINT, USINT, BYTE

0..7

16-bit

INT, UINT, WORD

0..15

32-bit

DINT, UDINT, DWORD

0..31

64-bit

LINT, ULINT, LWORD

0..63

A subrange of an integer type has the bits of its base type. Accessing a bit outside the valid range raises P4025.

IEC 61131-3 defines partial access on the bit-string types; IronPLC also accepts it on integers, in every dialect, as CODESYS and TwinCAT do. Any other type has no bits to select, and bit or partial access on it raises P4069: BOOL, REAL, STRING, TIME, an enumeration, a structure, a function block instance, or a whole array rather than one of its elements.

Example

PROGRAM main
    VAR
        flags : BYTE := 2#00000101;
        bit0  : BOOL;
        bit2  : BOOL;
    END_VAR

    bit0 := flags.0;        (* TRUE  — least significant bit *)
    bit2 := flags.2;        (* TRUE  *)
    flags.1 := TRUE;        (* set bit 1; flags becomes 2#00000111 *)
END_PROGRAM

Edition 3 Partial-Access Syntax

Note

This feature requires IEC 61131-3 Edition 3. Use --dialect iec61131-3-ed3 to enable it. See Enabling Dialects and Features for details.

IEC 61131-3:2013 adds the explicit form variable.%Xn for bit access. Semantically it is identical to the .n short form — IronPLC lowers both to the same representation. The Edition 3 form is gated behind --allow-partial-access-syntax.

Using .%Xn without the flag raises P4033.

PROGRAM main
    VAR
        my_byte_array : ARRAY[0..1] OF BYTE := [2#00000101, 2#00000000];
        r             : BOOL;
    END_VAR

    r := my_byte_array[0].%X0;     (* TRUE *)
    my_byte_array[0].%X1 := TRUE;  (* write bit 1 *)
END_PROGRAM

Byte / Word / Dword / Lword Partial Access

IEC 61131-3:2013 also defines partial access at wider granularities. Each form selects slice n of the base value, counting from the least significant end, and reads and writes as the bit-string type of that width:

Form

Width

Result type

Example

.%Bn

8 bits

BYTE

my_dword.%B2 — bits 16..23 of a DWORD

.%Wn

16 bits

WORD

my_lword.%W1 — bits 16..31 of an LWORD

.%Dn

32 bits

DWORD

my_lword.%D1 — bits 32..63 of an LWORD

.%Ln

64 bits

LWORD

my_lword.%L0 — all 64 bits of an LWORD

Slice n covers bits n * width through (n + 1) * width - 1 of the base value. Index 0 is the least significant slice.

The base may be any integer or bit-string type at least as wide as the slice. The valid index range depends on both widths:

Base type width

.%Bn

.%Wn

.%Dn

.%Ln

8-bit

0

—

—

—

16-bit

0..1

0

—

—

32-bit

0..3

0..1

0

—

64-bit

0..7

0..3

0..1

0

An index outside the valid range, or a slice wider than the base type, raises P4025.

Writing to a slice replaces only the bits of that slice; the other bits of the base value keep their values. Like .%Xn, these forms are gated behind --allow-partial-access-syntax and raise P4033 without it. Unlike .%Xn, they have no Edition 2 short form.

PROGRAM main
    VAR
        packet : DWORD := 16#AABBCCDD;
        lo     : BYTE;
        hi     : WORD;
    END_VAR

    lo := packet.%B0;         (* 16#DD — least significant byte *)
    hi := packet.%W1;         (* 16#AABB — upper 16 bits *)
    packet.%B1 := 16#FF;      (* packet becomes 16#AABBFFDD *)
END_PROGRAM

See Also

  • Assignment — assignment statement

  • BYTE — 8-bit bit string

  • WORD — 16-bit bit string

  • DWORD — 32-bit bit string

  • LWORD — 64-bit bit string

  • P4025 — bit index out of range

  • P4069 — variable has no bits to select

  • P4033 — partial-access syntax disabled