Learn PLCs free
Programming Guides16 min read3,179 words

PLC Data Types Explained: BOOL, INT, DINT, REAL, and More

PLC data types explained — BOOL, INT, DINT, REAL, WORD, and strings, their sizes and ranges, signed vs unsigned, and how to choose the right type.

PPI
PLC Programming IO Editorial Team
Sourced guidance with documented review and correction standards

Every variable in a PLC program occupies a defined amount of memory and can only hold values within a fixed range. Those two facts — size and range — are what a data type encodes. Pick the wrong type and your counter overflows at 32,767 instead of the expected 65,535, or your analog scaling loses precision. Pick a type that is too large and you waste memory on controllers where RAM is measured in kilobytes. This guide walks through every IEC 61131-3 elementary type, explains the signed-versus-unsigned distinction, maps vendor naming conventions across Allen-Bradley, Siemens, and IEC-compliant platforms, and ends with a practical decision framework for real control code.

What a Data Type Is (and Why It Matters)

A data type is a contract between your program and the processor. It tells the CPU three things:

  • How many bits to allocate for the variable in memory
  • What range of values that bit pattern can represent
  • How arithmetic and logic instructions should interpret the bits

Without a data type, the processor has no way to know whether the 32-bit value 0x00003039 is the integer 12,345, the floating-point number roughly 1.73 × 10⁻⁴¹, or four ASCII characters. The type is the interpretation layer.

This matters practically in industrial control for several reasons:

Memory constraints. Many embedded PLCs allocate a fixed data table. A small Micro820 or a safety-rated Siemens ET 200SP CPU may have only a few hundred kilobytes of work memory. Declaring a thousand variables as DINT (4 bytes each) when BOOL or INT would suffice wastes 4 MB of headroom you do not have.

Instruction compatibility. Move, compare, and math instructions are typed in every platform. A standard ADD instruction on a Logix controller operates on the declared type of the tag. Feeding a REAL into an integer ADD without an explicit conversion is either a compile error or an implicit truncation — both cause subtle bugs.

Communication and I/O mapping. Fieldbus messages, HMI tags, and historian writes all carry a type. If the PLC sends a DINT and the SCADA historian expects an INT, you get silent clipping at 32,767 — no alarm, just wrong data.

Understanding types is therefore a prerequisite for reliable programs. For context on where data types sit within the broader programming model, see the PLC programming basics fundamentals guide.

IEC 61131-3 PLC data type bit-width hierarchy — BOOL SINT INT DINT LINT REAL LREAL Horizontal bar chart showing the relative bit widths of IEC 61131-3 elementary data types from 1-bit BOOL up to 64-bit LINT and LREAL, with numeric ranges annotated on each bar. IEC 61131-3 Data Type Bit Widths BOOL 1 bit — 0 or 1 BYTE/SINT 8 bit — 0..255 / −128..+127 WORD/INT 16 bit — −32,768..+32,767 UINT 16 bit — 0..65,535 (unsigned) DWORD/DINT 32 bit — −2.1B..+2.1B REAL 32 bit IEEE 754 — ±3.4×10³⁸ (~7 digits) LINT/LREAL 64 bit — ±9.2×10¹⁸ int / ±1.8×10³⁰⁸ float 0 32 64 bits →
IEC 61131-3 data type bit widths: BOOL occupies 1 bit, integer types double from 8 to 64 bits, REAL and LREAL use IEEE 754 floating-point encoding at 32 and 64 bits.

The IEC 61131-3 Elementary Types

IEC 61131-3 defines a hierarchy of elementary data types. The table below covers every type a controls engineer encounters regularly, together with its storage size and the numerical range it can hold.

IEC 61131-3 Type Size Range / Notes
BOOL 1 bit (1 byte allocated) 0 or 1 (FALSE / TRUE)
BYTE 8 bits 0 to 255 (unsigned, no arithmetic intent)
SINT 8 bits −128 to +127 (signed integer)
USINT 8 bits 0 to 255 (unsigned integer)
WORD 16 bits 0 to 65,535 (bit-collection, no arithmetic intent)
INT 16 bits −32,768 to +32,767 (signed integer)
UINT 16 bits 0 to 65,535 (unsigned integer)
DWORD 32 bits 0 to 4,294,967,295 (bit-collection, no arithmetic intent)
DINT 32 bits −2,147,483,648 to +2,147,483,647 (signed integer)
UDINT 32 bits 0 to 4,294,967,295 (unsigned integer)
LINT 64 bits −9.2 × 10¹⁸ to +9.2 × 10¹⁸ (signed, not supported on all platforms)
REAL 32 bits ±1.18 × 10⁻³⁸ to ±3.40 × 10³⁸, ~7 significant decimal digits
LREAL 64 bits ±2.23 × 10⁻³⁰⁸ to ±1.80 × 10³⁰⁸, ~15–16 significant decimal digits
STRING Variable (default 80 or 82 bytes on many platforms) Zero-terminated character array
TIME 32 bits Duration: T#0ms to T#49d17h2m47s295ms
DATE 32 bits Calendar date: D#1970-01-01 to D#2106-02-06
TIME_OF_DAY 32 bits TOD#00:00:00 to TOD#23:59:59.999

Key reading notes for the table:

  • BYTE, WORD, and DWORD are bit-collection types, not arithmetic types. The standard intends them for bitwise operations and register mapping, not for addition or subtraction. Use USINT/UINT/UDINT when you need unsigned arithmetic.
  • REAL uses the IEEE 754 single-precision format. The ~7 significant digit limit means that the value 1,234,567.89 stored as a REAL will round to 1,234,568.0. This is the most common source of precision loss in PLC programs.
  • STRING size is implementation-defined. TIA Portal defaults to 254 characters; Studio 5000 Logix Designer defaults to 82 bytes (80 usable characters plus a length byte and null terminator). Always check your platform documentation.
  • TIME stores a duration internally as a DINT millisecond count, which is why its maximum is approximately 49 days.

Signed vs Unsigned: The Practical Difference

Signed types can represent negative values. Unsigned types cannot hold negative values but can represent twice as many positive values in the same number of bits.

The mechanism is two's complement representation. In a signed 16-bit INT, the most significant bit is the sign bit: 0 means positive, 1 means negative. That leaves 15 bits for magnitude, giving a range of −32,768 to +32,767. In an unsigned UINT, all 16 bits encode magnitude, giving 0 to 65,535.

When to use signed types:

  • Any quantity that can legitimately go negative: position error, temperature differential, torque setpoint
  • Counter values that can count down through zero (setpoint minus actual)
  • Offsets and trim values

When to use unsigned types:

  • Physical quantities that are always non-negative by definition: elapsed time, batch count, part count
  • Register mapping that must match Modbus or Profibus address offsets, which are inherently unsigned
  • Bit masks and flags where the sign bit interpretation would be wrong

A subtle trap: comparing a signed INT to an unsigned UINT in code that implicitly promotes types can produce wrong comparisons when the INT is negative and the UINT is zero. Explicit casting removes ambiguity. The PLC programming languages complete guide covers how Structured Text handles implicit type promotion rules.

Signed versus unsigned 16-bit integer PLC data types INT vs UINT range comparison Side-by-side comparison showing how a signed INT uses the MSB as a sign bit giving range -32768 to +32767, while an unsigned UINT uses all 16 bits for magnitude giving range 0 to 65535. INT — Signed 16-bit S 15 magnitude bits MSB = sign bit 0 = positive, 1 = negative −32,768 0 +32,767 Range: −32,768 to +32,767 Use for: error values, offsets, signed setpoints, temperatures UINT — Unsigned 16-bit All 16 bits = magnitude No sign bit All bits encode positive value 0 65,535 Range: 0 to 65,535 Use for: part counts, Modbus registers, non-negative quantities
Signed INT vs unsigned UINT: both use 16 bits, but INT dedicates the MSB as a sign bit, halving the positive range. UINT gives twice the positive range at the cost of no negative representation.

Bit, Word, and Double-Word Relationships

Understanding the hierarchy of bit widths helps when reading PLC manuals and mapping hardware I/O.

1 BOOL   = 1 bit
8 BOOLs  = 1 BYTE  (or SINT/USINT)
16 bits  = 1 WORD  (or INT/UINT)
32 bits  = 1 DWORD (or DINT/UDINT/REAL)
64 bits  = 1 LWORD (or LINT/ULINT/LREAL)

This hierarchy is not merely academic. On many older platforms, memory is addressed at the word (16-bit) level. Writing a single BOOL to a 16-bit word occupies the whole word in terms of addressing, even though only one bit changes. This is why PLC documentation distinguishes between bit-addressable memory (M-bits in Siemens, bit files in PLC-5) and word-addressed memory.

In practice:

  • Digital I/O arrives as BOOL or as packed BYTE/WORD from the I/O module
  • Analog I/O arrives as raw INT (typically 0–27,648 on Siemens, 0–32,767 on Logix) requiring scaling to REAL engineering units — see PLC math instructions for the scaling formula
  • Communication registers (Modbus, EtherNet/IP implicit messaging) use WORD or DINT as the fundamental transport unit, requiring explicit packing and unpacking of BOOL values
PLC memory hierarchy BOOL BYTE WORD DWORD nested bit structure Vertical stack diagram showing how 1 BOOL fits inside a BYTE, 2 BYTEs inside a WORD, 2 WORDs inside a DWORD, illustrating the nesting of PLC data type bit widths. PLC Memory Hierarchy — Bit to Double-Word DWORD / DINT / UDINT — 32 bits WORD (16 bits) WORD (16 bits) WORD / INT / UINT — 16 bits BYTE (8 bits) BYTE (8 bits) BYTE / SINT / USINT — 8 bits 4 bits 4 bits BOOL — 1 bit 2 × BYTE = 1 WORD 8 × BOOL = 1 BYTE smallest addressable unit 2 × WORD = 1 DWORD BOOL BYTE WORD/DWORD
PLC memory hierarchy: 8 BOOLs pack into 1 BYTE, 2 BYTEs form a WORD, and 2 WORDs form a DWORD. Digital I/O modules expose packed WORDs; individual bits are accessed by address offset.

Vendor Naming Conventions

IEC 61131-3 type names are not universally adopted. Each major vendor introduced naming conventions before or independently of the standard. The table below maps the most common equivalents.

Concept IEC 61131-3 Allen-Bradley (Logix 5000) Siemens (TIA Portal / S7)
Single bit BOOL BOOL BOOL
8-bit signed SINT SINT SINT
8-bit unsigned USINT USINT USINT
16-bit signed INT INT INT
16-bit unsigned UINT UINT UINT
32-bit signed DINT DINT DINT
32-bit unsigned UDINT UDINT UDINT
32-bit float REAL REAL REAL
64-bit float LREAL LREAL LREAL
16-bit bit-collection WORD — (use UINT) WORD
32-bit bit-collection DWORD — (use UDINT) DWORD
Character string STRING STRING STRING
Duration TIME — (use DINT ms) TIME

Allen-Bradley specific notes:

Studio 5000 Logix Designer is largely IEC-aligned for the numeric types listed above. The main divergence is that Logix does not use WORD or DWORD as distinct types — the closest equivalents are UINT and UDINT respectively. Logix also adds AXIS_SERVO, MESSAGE, CONTROL, and other controller-object types that have no IEC equivalent. The older PLC-5 and SLC 500 platforms used N (integer file), F (float file), B (bit file), and T/C/R (timer/counter/control files) — a file-based addressing model entirely different from the tag-based model.

Siemens specific notes:

TIA Portal (S7-1200/1500) follows IEC 61131-3 naming closely. The S7 Classic (S7-300/400) used Memory Bytes (MB), Memory Words (MW), and Memory Double Words (MD) for direct memory access — these are addressing prefixes, not type names, but they map onto BYTE/WORD/DWORD. TIA Portal preserves these addressing prefixes in absolute address mode but the preferred approach is symbolic tag-based programming using declared types.

Arrays, Structures (UDT), and Tags

Once you understand elementary types, the natural next step is grouping related data into compound types.

Arrays

An array is an ordered collection of elements of the same type, indexed by an integer offset.

(* Structured Text declaration *)
VAR
    ConveyorSpeeds : ARRAY[1..8] OF REAL;  (* 8 conveyor zone speeds *)
    AlarmBits      : ARRAY[0..15] OF BOOL; (* 16 alarm flags *)
END_VAR

Arrays are the right choice when you have a repeating structure of the same type — multiple drive setpoints, temperature readings from a sensor array, or recipe parameters indexed by product number. Accessing elements via loop index makes array-based code compact and easy to extend.

Key constraint: array bounds are fixed at declaration time on most platforms. Dynamic arrays are supported in some modern environments (CODESYS, TIA Portal S7-1500 with OB variant) but not universally.

Structures and User-Defined Types (UDT)

A structure groups variables of different types under a single name. In IEC 61131-3 these are called derived data types; vendors typically call them User-Defined Types (UDT) or Program Data Types (PDT).

(* UDT definition *)
TYPE Motor_Data :
STRUCT
    Running      : BOOL;
    FaultActive  : BOOL;
    SpeedSetpoint: REAL;    (* Hz *)
    SpeedActual  : REAL;    (* Hz *)
    CurrentDraw  : REAL;    (* A *)
    RunHours     : DINT;
END_STRUCT
END_TYPE

(* Instance declaration *)
VAR
    ConveyorMotor  : Motor_Data;
    MixerMotor     : Motor_Data;
END_VAR

UDTs offer significant engineering advantages:

  • Reuse: define the structure once, instantiate it for every drive, pump, or valve in the system
  • Consistency: every instance of a motor UDT has the same variable names, eliminating naming inconsistencies across the program
  • HMI/SCADA integration: the HMI connects to ConveyorMotor.SpeedActual — a self-describing path that is easier to maintain than positional register addresses
  • Structured Text readability: code like IF ConveyorMotor.FaultActive THEN is immediately clear to anyone reading the program

Nesting UDTs inside other UDTs is supported on most modern platforms, enabling hierarchical data models that mirror the physical equipment hierarchy. For more on writing UDT-heavy programs in Structured Text, see the structured text programming guide.

Tags

In tag-based systems (Logix 5000, TIA Portal, CODESYS), every variable is a named tag with a declared type. Tags can be scoped at the program level (local) or controller level (global). The tag name, data type, and description form the "single source of truth" for that variable — PLC addressing is resolved symbolically, not by raw memory address.

Choosing the Right Data Type

Selecting a data type is an engineering decision, not an afterthought. Apply these rules in order.

Step 1 — Define what the variable represents

Is it a physical I/O point (BOOL), a count (integer), a scaled measurement (REAL), or a duration (TIME)? The physical meaning immediately narrows the candidate types.

Step 2 — Determine the required range

What are the minimum and maximum values the variable will ever hold in normal and fault operation? Pick the smallest type whose range covers that span comfortably, with a safety margin.

Application Recommended Type Reason
Discrete input / output BOOL Single bit, direct I/O mapping
Counters (up to 32,767) INT Covers most production counts
Counters (up to 2.1 billion) DINT High-volume batching, odometers
Analog engineering units REAL Decimal precision needed
High-precision calculations LREAL When REAL's ~7 digits are insufficient
Modbus register value UINT or INT Matches 16-bit register width
Recipe parameters (mixed) UDT containing REAL/INT/BOOL Grouping for reuse
Timer preset / elapsed TIME or DINT (ms) TIME preferred; DINT if platform lacks TIME

Step 3 — Consider memory and scan time

On resource-constrained PLCs, prefer smaller types. On high-performance controllers, the difference between INT and DINT is negligible — go wider if there is any doubt about range. Floating-point arithmetic (REAL) costs more scan time than integer arithmetic on some embedded processors; profile before using REAL inside tight loops.

Step 4 — Match the communication protocol

If the value travels over Modbus TCP, EtherNet/IP, or PROFINET, check what type the receiving device expects. Modbus registers are 16-bit unsigned; sending a Logix DINT over a Modbus CIP path requires explicit packing into two registers. Mismatches here are a common commissioning headache that the right type declaration prevents.

The controls engineer's quick-reference view

  • BOOL — every physical I/O, every motor run/stop, every alarm flag
  • INT — small counts, HMI-facing setpoints with limited range
  • DINT — large counts (parts produced, encoder pulses), any integer that might exceed 32,767
  • REAL — analog signals scaled to engineering units (°C, bar, m/min), PID setpoints and outputs, ratio calculations
  • STRING — batch IDs, recipe names, operator messages, barcode values
  • UDT — any repeated equipment type (drives, valves, pumps, zones)

One practical rule: if you are scaling a 0–27,648 raw analog INT to a 0–100.0% REAL for display and control, do the scale in REAL arithmetic and store the result as REAL. Do not try to work in fixed-point integers — the code becomes opaque and the precision savings are rarely worth the maintenance burden.

PLC data type selection decision guide — BOOL INT DINT REAL UDT application mapping Vertical stack showing recommended PLC data types mapped to common industrial control applications: BOOL for I/O, INT for small counts, DINT for large counts, REAL for analog engineering units, UDT for equipment objects. Data Type Selection — Application Mapping BOOL Digital I/O, motor run/stop, alarm flags, permissives, valve open/closed 1 bit — TRUE / FALSE INT Small counters (≤32,767), HMI setpoints, Modbus registers, raw analog 16 bit signed — −32,768 to +32,767 DINT Large counts, encoder positions, runtime hours, any integer exceeding 32,767 32 bit signed — up to ±2,147,483,647 REAL Analog EU (°C, bar, m/min), PID setpoints/outputs, ratio calculations 32 bit IEEE 754 float — ~7 significant decimal digits UDT Repeated equipment: motors, pumps, valves — group BOOL/INT/REAL per instance Derived type — size depends on members; declared once, instantiated per device
PLC data type application guide: choose BOOL for all discrete I/O, INT for small counts, DINT for large counters, REAL for analog engineering units, and UDT to model repeated equipment objects.

Frequently Asked Questions

What are PLC data types?

PLC data types define the size, range, and interpretation of every variable in a PLC program. Each type allocates a fixed number of bits in controller memory and restricts what values the variable can hold. IEC 61131-3 standardizes the elementary types (BOOL, INT, DINT, REAL, STRING, TIME, and others) used across most modern PLC platforms.

What is the difference between INT and DINT?

Both are signed integers. INT occupies 16 bits and can hold values from −32,768 to +32,767. DINT occupies 32 bits and can hold values from −2,147,483,648 to +2,147,483,647. Use INT when your values are guaranteed to stay within the 16-bit range; use DINT for large counters, encoder positions, or any value that might exceed 32,767. On modern 32-bit PLCs, DINT arithmetic is no slower than INT arithmetic, so many programmers default to DINT for all integer work.

What is a REAL in a PLC?

REAL is a 32-bit floating-point type following the IEEE 754 single-precision standard. It can represent fractional values and very large or very small numbers (roughly ±3.4 × 10³⁸). REAL provides approximately 7 significant decimal digits of precision. It is the standard choice for analog engineering units — temperature in °C, pressure in bar, flow in m³/h — and for PID setpoints and outputs. When more precision is needed (high-resolution positioning, laboratory measurements), use LREAL (64-bit double-precision, ~15–16 significant digits).

What is a UDT in a PLC?

A UDT (User-Defined Type) is a custom data structure that groups multiple variables of different types under a single name. It is equivalent to a struct in C or a record in Pascal. UDTs are declared once and then instantiated for each piece of equipment that shares the same data model — for example, a single Pump_Data UDT containing BOOL, INT, and REAL members can be instantiated once per pump in the system. This enforces consistent naming, simplifies HMI tag browsing, and makes code reuse straightforward.

#plcdata types#BOOL#INT#DINT#REAL#IEC61131-3
Share this article:

Related Articles