CIP Data Types Complete Reference: Elementary, String, Time, and Structured Types

By | June 17, 2026

When you read an attribute from a CIP device, the bytes you get back have a type. When you write a value, you must encode it in the right type or the device returns an error. This page is the complete reference for every CIP data type defined by ODVA’s CIP Networks Library Volume 1, Appendix C.

CIP’s type system is aligned with IEC 61131-3 (the international standard for PLC programming languages), with a handful of CIP-specific extensions for paths, engineering units, and internationalized strings. The same types work across every CIP network — EtherNet/IP, DeviceNet, ControlNet, and CompoNet — because data typing is part of the CIP common specification, not the network adaptations.

This article completes the reference-page trio alongside our CIP General Status Codes Reference and CIP Service Codes Reference. For broader CIP context, see the CIP Protocol Complete Guide.

Quick jump — the types you’ll actually use

  • BOOL, SINT, INT, DINT, LINT — signed integers
  • USINT, UINT, UDINT, ULINT — unsigned integers
  • REAL and LREAL — IEEE 754 floats
  • STRING, SHORT_STRING, STRING2, STRINGN, STRINGI — character strings
  • BYTE, WORD, DWORD, LWORD — bit strings
  • DATE, TIME_OF_DAY, DATE_AND_TIME, TIME — time and date
  • EPATH — encoded CIP path
  • ENGUNIT — engineering units identifier
  • STRUCT, ARRAY — composite types

What CIP data types are

A CIP attribute is just a sequence of bytes on the wire. The data type tells you how to interpret those bytes — whether they are a 16-bit signed integer, a 32-bit float, a string, or something else. Every attribute defined by an object class specifies its data type in the spec.

The data type system has three layers:

  1. Elementary types — primitive types like INT, REAL, BOOL. These map directly to memory.
  2. String types — character strings with various encodings and length conventions.
  3. Derived types — composites built from elementary types: STRUCT, ARRAY, and combinations.

CIP also defines a set of type codes — single-byte identifiers used in EDS files and CIP-encoded data structures to specify which type a value uses. These codes start at 0xC1 (BOOL) and run through the elementary type range.

For full alignment with IEC 61131-3, see Section C-3 of Volume 1 Appendix C. CIP supports almost the entire IEC 61131-3 data type set with several extensions added (SHORT_STRING, STRING2, STRINGN, STRINGI, EPATH, ENGUNIT, FTIME, LTIME, ITIME).

Elementary integer types

The integer types are the workhorses of CIP. They cover every signed and unsigned width from 8 to 64 bits.

TypeType CodeSizeRangeIEC 61131-3 equivalent
BOOL0xC11 byte (1 bit value)0 (FALSE) or 1 (TRUE)BOOL
SINT0xC21 byte-128 to 127SINT
INT0xC32 bytes-32,768 to 32,767INT
DINT0xC44 bytes-2,147,483,648 to 2,147,483,647DINT
LINT0xC58 bytes-2^63 to 2^63-1LINT
USINT0xC61 byte0 to 255USINT
UINT0xC72 bytes0 to 65,535UINT
UDINT0xC84 bytes0 to 4,294,967,295UDINT
ULINT0xC98 bytes0 to 2^64-1ULINT

Endianness

All elementary types are transmitted in little-endian byte order on the wire. The least significant byte comes first.

Example: the UINT value 0x1234 (4660 decimal) is transmitted as 34 12 on the wire. The DINT value 0x12345678 is transmitted as 78 56 34 12.

This is the same convention used by the EtherNet/IP encapsulation header and matches Intel x86 architecture. It is the opposite of standard “network byte order” used by TCP/IP, which is one of the reasons custom CIP parsers occasionally fail when developers default to big-endian. For more on this gotcha, see our EtherNet/IP Encapsulation Protocol Explained article.

BOOL — the special case

BOOL is logically 1 bit but transmitted as 1 byte. Value 0 = FALSE, any non-zero = TRUE. The spec says only 0 and 1 are defined values, but devices generally accept any non-zero byte as TRUE on read.

When BOOL values appear inside structures, they often pack into byte arrays — 8 BOOLs per byte. The Discrete Input/Output Point Objects use this packing for their assemblies. The bit numbering within a byte is little-endian: bit 0 is the least significant.

Floating-point types

CIP uses standard IEEE 754 floats — same as nearly every modern computer language.

TypeType CodeSizeFormatIEC 61131-3 equivalent
REAL0xCA4 bytesIEEE 754 single-precision (32-bit)REAL
LREAL0xCB8 bytesIEEE 754 double-precision (64-bit)LREAL

REAL gives roughly 7 decimal digits of precision. LREAL gives roughly 15 decimal digits.

Both are transmitted little-endian. So a REAL value of 1.0 (IEEE 754 hex 0x3F800000) is transmitted as 00 00 80 3F on the wire.

REAL is by far the more common in field devices. LREAL appears in higher-precision motion controllers and analytical instruments where the extra precision matters.

Bit string types

Bit string types treat a value as a fixed-width collection of bits, with no integer interpretation. They are used for status registers, flag words, and bitmask attributes.

TypeType CodeSizeUse
BYTE0xD11 byte8-bit status flags
WORD0xD22 bytes16-bit status flags
DWORD0xD34 bytes32-bit status flags
LWORD0xD48 bytes64-bit status flags

The bits within these types are accessed by position: bit 0 is the least significant bit, bit N-1 is the most significant. Many CIP status attributes are WORDs where each bit means something specific (e.g., the Identity Object’s Status attribute uses a WORD with bits for “Owned,” “Configured,” “Major Recoverable Fault,” “Major Unrecoverable Fault,” etc.).

Like all elementary types, bit strings are transmitted little-endian.

String types

CIP defines several string types because different applications need different character widths and length conventions. This is one of the areas where CIP extends IEC 61131-3.

TypeType CodeLength prefixCharacter widthEncoding
STRING0xD0UINT (2 bytes)1 byteISO-8859-1
STRING20xD5UINT (2 bytes)2 bytesISO 10646 (Unicode)
STRINGN0xD9UINT + UINT (4 bytes)N bytesISO 10646
SHORT_STRING0xDAUSINT (1 byte)1 byteISO-8859-1
STRINGI0xDEUSINT (count)Variable per languageMultilingual structure

STRING

A UINT length prefix followed by that many bytes of ISO-8859-1 (Latin-1) characters. The most common general-purpose string type. Length can be 0 to 65,535 characters.

Example: the string “Hello” encoded as STRING is:

STRING

(0x0005 in little-endian = 5 characters)

SHORT_STRING

Same idea but with a 1-byte (USINT) length prefix. Maximum length 255 characters. Common in DeviceNet devices where every byte matters.

Example: the string “OK” encoded as SHORT_STRING is:

SHORT STRING

The Identity Object’s Product Name attribute (Class 0x01, Instance 1, Attribute 7) is a SHORT_STRING. Every CIP device’s name comes through this type.

STRING2

A UINT length prefix followed by that many 16-bit characters in ISO 10646 (basic Unicode plane). Each character takes 2 bytes, little-endian. Length prefix counts characters, not bytes.

Example: “Hi” as STRING2 takes 6 bytes (2-byte length + 2 × 2-byte characters):

02 00 48 00 69 00

STRINGN

For arbitrary character widths. Includes both a character count (UINT) and a character size (UINT, in bytes). Almost never seen in field devices but allowed by the spec for specialized internationalization needs.

STRINGI — the internationalized string

STRINGI is the most complex string type. It represents a string with multiple language variants. The structure:

  1. A USINT count of how many language variants follow
  2. For each variant:
    • 3-byte ISO 639-2/T language code (e.g., “eng”, “fra”, “deu”)
    • 1-byte EPATH segment (limited to 0xD0, 0xD5, 0xD9, or 0xDA — meaning STRING, STRING2, STRINGN, or SHORT_STRING)
    • UINT character set identifier (IANA MIB Printer Codes — 4 = ISO-8859-1, 1000 = ISO-10646-UCS-2, etc.)
    • The actual string in the indicated type

Common ISO 639-2/T language codes engineers see:

LanguageCode
Englisheng
Frenchfra
Spanishspa
Italianita
Germandeu
Japanesejpn
Portuguesepor
Chinesezho
Russianrus

STRINGI is used by devices that need to expose multilingual product information. A drive sold worldwide might have its parameter descriptions in 8 languages, each stored as one variant within a STRINGI attribute.

Time and date types

CIP defines several time types with different resolutions and ranges.

TypeType CodeSizeResolutionRange
TIME0xDB4 bytes1 millisecond±24 days
FTIME0xD64 bytes1 microsecond±35 minutes
LTIME0xD78 bytes1 microsecond±106,751,991 days
ITIME0xD82 bytes1 millisecond±32.768 seconds
DATE0xCD2 bytes1 day1972-01-01 to 2151-06-06
TIME_OF_DAY0xCE4 bytes1 millisecond00:00:00.000 to 23:59:59.999
DATE_AND_TIME0xCF8 bytes1 millisecondDT#1972-01-01-00:00:00.000 to DT#2151-06-06-23:59:59.999

TIME and FTIME

TIME is a 32-bit signed value representing duration in milliseconds. Range is roughly ±24 days. Common for timeouts, watchdogs, and elapsed times.

FTIME is also 32-bit signed but in microseconds, so the range is only ±35 minutes. Used where sub-millisecond resolution matters but durations stay short — handshake timing, motion command intervals.

DATE

DATE counts days since 1972-01-01 (the start of the UTC era) as a 16-bit value. With 65,536 possible values, the range extends to 2151-06-06. Not as long-lived as a 32-bit Unix timestamp, but enough for most industrial applications.

TIME_OF_DAY

TIME_OF_DAY is a 32-bit value representing milliseconds since midnight. Range 0 to 86,399,999 covers 00:00:00.000 to 23:59:59.999.

DATE_AND_TIME

A 64-bit composite that combines DATE and TIME_OF_DAY. Lower 32 bits are TIME_OF_DAY (milliseconds since midnight). Upper 32 bits are DATE (days since 1972-01-01, zero-padded). Common in event logs and audit trails.

CIP-specific data types

These types are CIP extensions to IEC 61131-3 — they don’t exist outside the CIP world.

EPATH

Type code: 0xDC

EPATH is the encoded path type. It represents a CIP path (Class, Instance, Attribute, or routing path) in compact binary form. Almost every CIP message contains at least one EPATH.

An EPATH is a sequence of segments, each of which is one or more bytes describing one element of the path. Common segment types:

  • Logical Segment (0x20-0x3F) — Class ID, Instance ID, Attribute ID, Connection Point ID, Member ID
  • Port Segment (0x00-0x0F) — Routing through a network port to another network
  • Symbolic Segment (0x60-0x6F) — Tag name reference (used heavily by Logix systems)
  • Network Segment (0x40-0x5F) — Network-specific parameters
  • Data Segment (0x80-0x9F) — Embedded data (used in Forward_Open for the connection’s application path)

Example: the EPATH for “Class 0x01, Instance 1, Attribute 7” encodes as:

EPATH

Each segment is 2 bytes. 20 is the Class segment type (8-bit logical class), followed by the class ID. 24 is the Instance segment type, followed by the instance ID. 30 is the Attribute segment type, followed by the attribute ID.

For values above 255, 16-bit logical segment types (0x21, 0x25, 0x31) take 4 bytes per segment.

EPATH is what makes CIP routing possible. The path tells the receiver exactly where to send the message, including across network boundaries.

ENGUNIT

Type code: 0xDD

ENGUNIT is a 16-bit identifier (UINT) that references a specific engineering unit defined in Volume 1 Appendix D. It lets attributes self-document their physical units.

Examples (from Volume 1 Appendix D):

ENGUNIT valueUnit
0x0000(no units / dimensionless)
0x1010meter
0x101Ckilometer
0x103Efoot
0x1056meter per second
0x2008volt
0x2018ampere
0x4080kelvin
0x4081degree Celsius
0x40C0newton
0x40C8pascal
0x4100hertz
0x4810second
0x4828hour

When a configuration tool reads an attribute marked with an ENGUNIT companion attribute, it can display the value with the right units. A device exposing a temperature reading at attribute 5 might expose its ENGUNIT (0x4081 = degree Celsius) at attribute 6. The tool reads both and shows “23.5 °C” automatically.

Many devices skip ENGUNIT and just document units in their manual. When ENGUNIT is present, it makes the device self-describing.

Structured types

CIP supports composite types built from elementary and string types.

TypeType CodeDescription
STRUCT0xA2A composite of multiple named members of different types
ABBREV_STRUCT0xA0Compact struct without member type tags (saves bytes when the structure is known)
ARRAY0xA3Fixed-size sequence of one type
ABBREV_ARRAY0xA1Compact array without element type tags

STRUCT

A STRUCT has a type code (0xA2), then a definition listing each member’s type code and data. Used for attributes that bundle related fields.

Example: the Identity Object’s Revision attribute is a STRUCT of two USINTs (Major and Minor):

STRUCT

When the structure is known in advance (the spec defines it), ABBREV_STRUCT (0xA0) can be used to save the per-member type code bytes.

ARRAY

An ARRAY is a fixed-size sequence of one type. The type code (0xA3) is followed by the element count and the elements themselves.

Used for things like “list of registered protocols” or “device serial numbers of bridged devices.” Most field devices avoid ARRAY in favor of multiple instances of the same object class (which is generally cleaner), but it appears in network and routing objects.

User-Defined Data Types in Logix

Rockwell ControlLogix and CompactLogix expose tags as STRUCTs with named members. When an external client reads a structured tag through CIP, the data comes back as a CIP STRUCT. The Logix Symbol Object handles the mapping between the Logix tag’s user-defined structure and the wire-format STRUCT.

This is what makes the Logix tag-based addressing experience feel seamless even though CIP underneath is reading bytes.

Complete data type code table

The full list of CIP elementary and derived type codes, sorted by code:

CodeTypeSize
0xA0ABBREV_STRUCTVariable
0xA1ABBREV_ARRAYVariable
0xA2STRUCTVariable
0xA3ARRAYVariable
0xC1BOOL1 byte
0xC2SINT1 byte
0xC3INT2 bytes
0xC4DINT4 bytes
0xC5LINT8 bytes
0xC6USINT1 byte
0xC7UINT2 bytes
0xC8UDINT4 bytes
0xC9ULINT8 bytes
0xCAREAL4 bytes
0xCBLREAL8 bytes
0xCCSTIME4 bytes (synchronous time)
0xCDDATE2 bytes
0xCETIME_OF_DAY4 bytes
0xCFDATE_AND_TIME8 bytes
0xD0STRINGVariable (UINT length)
0xD1BYTE1 byte
0xD2WORD2 bytes
0xD3DWORD4 bytes
0xD4LWORD8 bytes
0xD5STRING2Variable (UINT length, 2 bytes/char)
0xD6FTIME4 bytes
0xD7LTIME8 bytes
0xD8ITIME2 bytes
0xD9STRINGNVariable
0xDASHORT_STRINGVariable (USINT length)
0xDBTIME4 bytes
0xDCEPATHVariable
0xDDENGUNIT2 bytes
0xDESTRINGIVariable (multi-language)

These codes are what you see in EDS files (parameter type fields) and in any wire-level encoding that includes type tags.

Mapping CIP types to common languages

A reference table for developers writing CIP code:

CIP typeC / C++C# / .NETPython (struct module)Java
BOOLbool / uint8_tbool (1 byte)? or bboolean (8-bit on wire)
SINTint8_tsbytebbyte
INTint16_tshort<hshort
DINTint32_tint<iint
LINTint64_tlong<qlong
USINTuint8_tbyteBbyte (unsigned via mask)
UINTuint16_tushort<Hshort (unsigned via mask)
UDINTuint32_tuint<Iint (unsigned via mask)
ULINTuint64_tulong<Qlong (unsigned via mask)
REALfloatfloat<ffloat
LREALdoubledouble<ddouble

The < in Python’s struct format strings forces little-endian (CIP order). Without it, Python uses native byte order, which causes silent bugs on big-endian platforms.

Common gotchas

Endianness mismatch

The most common bug in custom CIP code. CIP is little-endian. TCP/IP, IP, and Ethernet headers are big-endian. Custom parsers that default to network byte order (big-endian) read CIP values wrong without obvious errors — just nonsense data.

STRING vs SHORT_STRING confusion

These look almost identical but have different length prefix sizes (UINT for STRING, USINT for SHORT_STRING). Reading a SHORT_STRING as a STRING gives you the first byte of the string mixed with the count. Some Identity Object attributes are SHORT_STRING; STRING is more common in general attributes.

BOOL in arrays

A single BOOL is 1 byte. But many BOOLs packed in an array of BOOLs (or in the bits of a BYTE/WORD/DWORD) use 1 bit each. The Discrete Input Object’s input data is a packed BOOL array — 8 inputs per byte. Misreading this as 8 separate bytes gives you wrong values.

Floating-point conversion

REAL is IEEE 754, but custom code that types float x = *(float*)bytes; only works on little-endian platforms with IEEE 754 native. On other platforms, swap bytes first then use memcpy to avoid alignment issues.

Time type ranges

TIME is in milliseconds with a 32-bit signed value — range ±24 days. A device using TIME for elapsed time wraps around 24 days. For longer durations, use LTIME (microseconds in a 64-bit value) or just store seconds in a DINT.

Sign extension

When reading a SINT or INT into a larger type, sign-extend it. A SINT value of -1 is byte 0xFF — read into a UDINT it becomes 255, not -1. Use proper signed-to-larger-signed conversion.

Reading data types in Wireshark

Wireshark’s CIP dissector handles common types automatically when the attribute being read is known. For unknown attributes, you see the raw bytes.

Filters that help:

cip                                      # All CIP traffic
cip.service == 0x8E                      # Get_Attribute_Single replies (carry typed data)
cip.data_seg                             # Frames containing Data Segments (often typed data)
cip.epath                                # Frames containing EPATH content

When debugging type issues, capture the request and reply for an attribute you know the spec definition of, then verify the byte layout matches what the spec says. EDS files for the device often document each attribute’s exact data type.

Frequently asked questions

What is the difference between SINT, INT, DINT, and LINT in CIP?

These are signed integer types of increasing width. SINT is 8-bit (-128 to 127), INT is 16-bit (-32,768 to 32,767), DINT is 32-bit (about ±2.1 billion), and LINT is 64-bit (about ±9.2 quintillion). All are transmitted little-endian. The unsigned equivalents are USINT, UINT, UDINT, and ULINT.

What is the type code for a REAL in CIP?

The type code for REAL is 0xCA. REAL is a 4-byte IEEE 754 single-precision floating-point value. The 8-byte double-precision equivalent is LREAL with type code 0xCB. Both are transmitted little-endian on the wire.

What is the difference between STRING and SHORT_STRING?

STRING uses a 2-byte UINT length prefix and can hold up to 65,535 characters. SHORT_STRING uses a 1-byte USINT length prefix and can hold up to 255 characters. Both use ISO-8859-1 (Latin-1) encoding. SHORT_STRING is common in DeviceNet devices where bytes are at a premium. The Identity Object’s Product Name attribute is a SHORT_STRING.

Is CIP little-endian or big-endian?

CIP is little-endian. All multi-byte elementary types — INT, DINT, REAL, LREAL, UINT, UDINT, ULINT, etc. — are transmitted least-significant byte first. This is unusual because most Internet protocols use big-endian (network byte order). The EtherNet/IP encapsulation header is also little-endian to match CIP, but the surrounding TCP/IP, UDP/IP, and Ethernet headers are big-endian.

What is EPATH in CIP?

EPATH (Encoded Path, type code 0xDC) is the CIP data type that represents a path to an object — typically a sequence of Logical Segments for Class ID, Instance ID, and Attribute ID. EPATH is used in nearly every CIP message because every message must reference a target object. It also supports Port Segments for routing across networks and Symbolic Segments for tag-name references.

What is ENGUNIT in CIP?

ENGUNIT (type code 0xDD) is a 16-bit identifier that specifies an engineering unit — meters, volts, degrees Celsius, hertz, etc. The values are defined in Volume 1 Appendix D of the CIP specification. When a device attribute carries a measured value, a companion ENGUNIT attribute lets configuration tools display the value with its correct unit automatically.

How does CIP handle multilingual strings?

Through the STRINGI type (type code 0xDE). A STRINGI value contains one or more language variants, each tagged with an ISO 639-2/T language code (“eng”, “fra”, “deu”, etc.) and a character set identifier. Devices that need to expose multilingual product information — parameter descriptions, fault messages — use STRINGI to carry every supported language in one attribute.

What is the type code for STRUCT in CIP?

STRUCT has type code 0xA2. It is followed by the structure’s members, each with their own type code and value. The compact variant ABBREV_STRUCT (0xA0) omits the per-member type tags when the structure layout is already known from the object specification. ARRAY (0xA3) is the type code for fixed-size sequences of one type.

Why does CIP have so many time types?

Different resolutions and ranges. TIME (4 bytes, milliseconds, ±24 days) covers most general timeouts. FTIME (4 bytes, microseconds, ±35 minutes) provides higher resolution for short durations. LTIME (8 bytes, microseconds, ±106M days) provides both. ITIME (2 bytes, milliseconds, ±32.7 seconds) is compact for very short durations. DATE, TIME_OF_DAY, and DATE_AND_TIME are absolute time types rather than duration types.

How are CIP data types related to IEC 61131-3?

CIP data types align closely with the IEC 61131-3 PLC programming standard. BOOL, SINT, INT, DINT, LINT, USINT, UINT, UDINT, ULINT, REAL, LREAL, BYTE, WORD, DWORD, LWORD, TIME, DATE, TIME_OF_DAY, DATE_AND_TIME, and STRING all come directly from IEC 61131-3. CIP adds extensions: SHORT_STRING, STRING2, STRINGN, STRINGI (for various string formats), EPATH (for paths), ENGUNIT (for engineering units), FTIME, LTIME, ITIME (for additional time resolutions).

Where can I find the complete CIP engineering units list?

The complete list is in ODVA’s CIP Networks Library Volume 1, Appendix D. It defines hundreds of standardized unit identifiers for length, area, volume, time, mass, force, pressure, energy, power, electrical, magnetic, optical, thermal, and chemical units. The ENGUNIT data type (0xDD) carries the 16-bit identifier value. ODVA members can access the full specification at odva.org.

Are CIP data types the same on EtherNet/IP, DeviceNet, and ControlNet?

Yes. CIP data types are defined in the CIP common specification (Volume 1, Appendix C), not in any network-specific volume. A DINT on EtherNet/IP is the same as a DINT on DeviceNet — 4 bytes, signed, little-endian. The type system is one of the things that makes CIP truly media-independent.

Author: Zakaria El Intissar

I'm an automation and industrial computing engineer with 12 years of experience in power system automation, SCADA communication protocols, and electrical protection. I build tools and write guides for Modbus, DNP3, IEC 101/103/104, and IEC 61850 on ScadaProtocols.com to help engineers decode, analyze, and troubleshoot real industrial communication systems.