RPGLE Constants and Literals

Once you can declare variables and group them into data structures, the next question is what to do with values that should not change while the program runs. RPGLE gives you two ways to write such a value: a named constant, declared with DCL-C, and a literal, written directly at the point of use. Neither is a variable, and confusing the three leads to some of the most common misreadings of otherwise simple code.

This reference explains RPGLE constants and literals through small, IBM-verified examples: how to declare a named constant, how character, numeric, and typed literals are written, which figurative constants remain relevant in modern code, and when a literal is a perfectly reasonable choice versus when it should get a name.

The starting point is RPGLE Variables and Storage Types, which introduced named, mutable storage. RPGLE Data Structures Explained then grouped related fields together. This article stays on the other side of that boundary: values that are not supposed to change.

Quick Summary

  • A variable is named storage whose value may change while the program runs. A named constant is a name bound once to a value that stays fixed. A literal is a value written directly in source code, with no name at all.
  • A free-form named constant begins with DCL-C, followed by the name, followed by the value — either written directly or wrapped in the CONST keyword. IBM documents no difference in meaning between the two forms.1
  • Character literals are delimited by apostrophes; an apostrophe inside the value is written as two apostrophes.3
  • RPGLE has its own typed-literal notation for dates, times, and timestamps — D'...', T'...', and Z'...' — distinct from anything borrowed from SQL.3
  • Figurative constants such as *ON, *OFF, *BLANK, *ZERO, *HIVAL, and *LOVAL are predefined values, each restricted to specific field types.2
  • A numeric named constant has no predefined precision of its own; its precision comes from the context where it is used.3 That is not the same as saying a constant “has no type.”
  • Replacing an unexplained literal with a named constant is a readability choice, not an IBM requirement. Not every literal needs a name.

Variable, Constant, or Literal?

Compare three ways of expressing the same idea, a customer’s tax rate:

dcl-s taxRate packed(5:4);
dcl-c DefaultTaxRate const(0.18);
if orderStatus = 'A';

taxRate is a variable: named, typed storage that some later line of code is free to reassign. DefaultTaxRate is a named constant: a name bound once to 0.18 that stays that value for the rest of the program. The literal 'A' in the third line has no name at all — it is a value written directly where it is needed, and there is nothing else in the source that identifies what 'A' is supposed to represent.

None of the three is a data structure, and this article does not revisit DCL-DS, subfields, or LIKEDS; see RPGLE Data Structures Explained for that mechanics. It also does not cover how values move into and out of a procedure — passing a constant, a literal, or a variable as a parameter is a distinct topic reserved for a later lesson.

ConstructSource formRuntime mutabilityTypical useCaution
Variabledcl-s taxRate packed(5:4);May change during executionA value that legitimately varies as the program runsDo not declare a variable for a value that is really fixed
Named constantdcl-c DefaultTaxRate const(0.18);Fixed after compilationA business-rule value, threshold, or status code used more than onceIts precision comes from context, not from the DCL-C line itself3
Literal0.18 written inlineFixed, and has no name to reassignA genuinely one-off, self-explanatory valueRepeated or unexplained literals become magic values
Figurative constant*zero, *blanks, *onFixed, predefined by IBMA field’s documented all-zero, all-blank, or on/off stateRestricted to the specific field types IBM documents for each one2
A value your program needs branches three ways: a variable such as DCL-S taxRate PACKED(5:4), which is named and may change at runtime; a named constant such as DCL-C DefaultTaxRate 0.18, which is named and holds a stable value; and a literal such as 0.18 written directly, which has no name and is fixed in place.
A conceptual comparison, not a memory-layout or performance diagram.

Reader Prerequisites

This article assumes you are comfortable with DCL-S, standalone-field declarations, and the distinction between a variable’s scope and its lifetime, from RPGLE Variables and Storage Types. It also assumes the scalar type vocabulary from RPGLE Data Types, Lengths, and Precision — character, packed decimal, integer, date, time, and timestamp — without repeating their full parameter rules here.

No knowledge of data structures, procedure parameters, or IF/ELSE control-flow syntax is required. Where an example uses a simple IF to compare a value, it is there only to show a constant or literal in a realistic comparison, not to teach conditional logic.

Learning Outcomes

After working through this reference, you should be able to:

  1. Explain the difference between a variable, a named constant, and a literal.
  2. Declare a named constant with DCL-C, in either of its two equivalent forms.
  3. Write ordinary character, numeric, and typed literals correctly.
  4. Recognize the handful of figurative constants relevant to modern code, and know which field types accept each one.
  5. Decide, as an editorial judgment rather than a compiler rule, when a literal should become a named constant.
  6. Recognize a legacy fixed-format constant declaration and map it to its modern DCL-C equivalent.

DCL-C Anatomy

A free-form named constant definition begins with DCL-C, followed by the constant’s name, followed by its value — specified either directly or with the CONST keyword — and ends with a semicolon. IBM documents that there is no difference in meaning between writing the value directly and wrapping it in CONST.1

dcl-c MaxRetries const(3);
dcl-c StatusActive 'A';

MaxRetries and StatusActive are declared identically in effect: one spells out CONST, the other does not. Pick whichever reads more clearly in context; this article uses both styles so you can recognize either one in existing code.

A named constant’s value can itself be a typed literal:

dcl-c ReleaseDate const(D'2026-01-01');

ReleaseDate is a named constant whose value is a date literal (typed literals are covered in full below). The DCL-C line does not declare a data type the way DCL-S does — there is no CHAR, PACKED, or DATE keyword on it. The constant simply takes on whatever value you give it.

A related but distinct mechanism. IBM also lets you mark an ordinary standalone field as CONST, which prevents that specific field from being changed after its initial value is set:

dcl-s startedAt timestamp inz(*sys) const;

This is IBM’s own documented pattern for a field that should be set once and never reassigned.3 It is worth knowing about, but it is a different mechanism from a DCL-C named constant: startedAt is still a standalone field with a declared type (TIMESTAMP) and an initial value (INZ(*SYS)); it simply cannot be changed after that. A DCL-C named constant, by contrast, is never a variable in the first place. This article’s focus stays on DCL-C; the CONST keyword on a standalone field is mentioned here only so the two are not confused.

Named Constants

Named constants are most useful for values that mean something specific and are used in more than one place: status codes, thresholds, limits, and business-rule values.

dcl-c StatusActive const('A');

Practical guidance: giving 'A' the name StatusActive tells the next reader what the value represents without them having to trace back to wherever the status code was first defined. That benefit is an editorial one — IBM does not require named constants for any particular value, and a genuinely self-explanatory literal does not need a name just because one is available.

IBM’s own documentation makes one further point that is easy to state wrong: a numeric named constant has no predefined precision of its own. Its actual precision comes from the context in which it is used.3 That is a narrower, more accurate claim than saying “a constant has no type” — the constant’s value is exact and well-defined; it simply does not carry a fixed decimal length and scale the way a DCL-S declaration does, because nothing forced it to.

Character Literals

A character literal is any combination of characters enclosed in apostrophes. An empty character literal, with nothing between the apostrophes, is allowed. If the value itself needs to contain an apostrophe, write it as two apostrophes in a row.3

status = 'A';

For example, the word O'CLOCK would be written as the literal 'O''CLOCK'. Character literals are compatible only with character data — do not assign one directly to a numeric or date field and expect an implicit conversion of the text itself.3

A closely related form is the hexadecimal literal, written as X followed by an even number of hex digits in apostrophes:

rawByte = X'40';

A hexadecimal literal is generally treated the same as the equivalent character literal; X'40' is the EBCDIC blank character, so this line has the same effect as rawByte = ' ';. IBM’s rules also allow a short hexadecimal literal (16 digits or fewer) to be treated as an unsigned numeric value in a numeric expression or INZ initialization, but its ordinary home is anywhere a character literal is accepted.3

Numeric Literals

A numeric literal is any combination of the digits 0 through 9, with an optional decimal point and an optional sign. If a sign is present, it must be the leftmost character; an unsigned literal is treated as positive. Numeric literals are never enclosed in apostrophes, and blanks cannot appear inside one. The decimal separator may be either a period or a comma.3

orderTotal = 149.99;

Unlike a character literal, a numeric literal cannot be assigned to — you use it as a value, not as a target. Where a numeric literal ends up (a packed field, an integer field, and so on) determines how it is interpreted; see RPGLE Data Types, Lengths, and Precision for how those target types work.

IBM also documents a separate float literal form for the floating-point family, written as a mantissa followed by E (or e) and a signed exponent, for example 1.2E-1. Float literals follow their own normalization and range rules and are not required for ordinary business values; this article does not go further into them, beyond noting that they exist and are not simply “numeric literals with an E in them” from an arithmetic standpoint.3

Typed Literals

RPGLE has its own native notation for date, time, and timestamp values, distinct from anything used in SQL. Each typed literal is a value enclosed in apostrophes and preceded by a one-letter type code:

cutoverDate = D'2026-01-01';
cutoverTime = T'08:30:00';
recordedAt = Z'2026-01-01-08.30.00';
  • A date literal takes the form D'xx-xx-xx'. The date inside the apostrophes must use the format set by the DATFMT control-specification keyword, separator included — so a date literal written for DATFMT(*ISO) looks different from one written for DATFMT(*USA).3
  • A time literal takes the form T'xx:xx:xx', matching whatever format the TIMFMT keyword sets. The *HMS format (hours:minutes:seconds, colon-separated) is what the example above assumes.3
  • A timestamp literal takes the form Z'yyyy-mm-dd-hh.mm.ss', optionally followed by a period and up to twelve fractional-second digits. Unlike date and time literals, its format is fixed and does not depend on DATFMT or TIMFMT. Fewer than six fractional digits are padded with trailing zeros.3

IBM’s reference also documents graphic (G'...') and UCS-2 (U'...') typed literals for double-byte character data.3 They exist for completeness here; this article does not teach CCSID or Unicode handling, and an ordinary business application is unlikely to need them for the values covered in this lesson.

A named constant can hold a typed literal exactly the way it holds any other literal, as shown earlier with ReleaseDate const(D'2026-01-01').

Special / Figurative Constants

A figurative constant is a predefined, reserved-word value — not something you declare yourself. IBM documents figurative constants as implied literals whose length and decimal positions come from whatever field they are used with.2 The six most relevant to ordinary modern code are:

FormMeaningExampleContextCaution / restriction
*ON / *OFFAll ones ('1', X'F1') / all zeros ('0', X'F0')flag = *on;Character fields, including indicatorsDocumented as valid only for character fields — not numeric, date, time, or timestamp fields2
*ZERO / *ZEROSAll zeroscounter = *zero;Character and numeric fieldsMeaning depends on the field’s type; a numeric float field’s zero is written 0 E02
*BLANK / *BLANKSAll blanksname = *blanks;Character, graphic, or UCS-2 fieldsNot documented for numeric, date, time, or timestamp fields2
*HIVALHighest value for the field’s typelargestId = *hival;Character, graphic, UCS-2, or numeric fieldsFor character-family fields this is the highest collating character, not a numeric maximum2
*LOVALLowest value for the field’s typesmallestId = *loval;Character, graphic, UCS-2, or numeric fieldsSymmetric with *HIVAL: lowest collating character for character-family fields, minimum value for numeric fields2
flag = *on;
flagChar = *off;
name = *blanks;
smallestId = *loval;
largestId = *hival;
counter = *zero;

*ON and *OFF are not a general-purpose stand-in for any character value. IBM restricts both to character fields.2 They are exactly what makes *inlr = *on; — the last-record indicator assignment you have already seen in every example in this cluster — work: *INLR is a character-shaped indicator field, and *ON is its documented on-value.

IBM also documents a larger family of figurative constants for less common needs — *NULL for basing pointers, and the repeating forms *ALL'x..', *ALLG'...', *ALLU'...', and *ALLX'...' for filling a field with a repeated pattern.2 This reference does not cover them further; the six above are the ones you are most likely to need or encounter.

One restriction worth remembering: figurative constants are not allowed when a variable is defined like an enumeration.2 Enumerations are their own topic and are outside this article’s scope.

Type Behavior of Constants

It is tempting to simplify a named constant’s typing by saying it “has no type.” That is not what IBM documents, and it is not accurate. What IBM actually says is narrower: a numeric named constant has no predefined precision, and its precision is determined by the context where it is used.3

In practice, this means a constant like dcl-c DefaultTaxRate const(0.18); does not carry its own fixed number of decimal digits the way dcl-s taxRate packed(5:4); does. When DefaultTaxRate is assigned into taxRate, it is taxRate‘s declared type and precision that govern the result — the constant supplies the value, not a competing set of type rules. A character or typed-literal constant behaves the same way in spirit: its value is exact, but its “shape” comes from where you use it, not from a type keyword on the DCL-C line, because there is no type keyword on a DCL-C line at all.

When to Replace a Literal with a Named Constant

Consider a comparison that most RPGLE readers have seen in one form or another:

if status = 'A';
   beforeLabel = 'before: match';
else;
   beforeLabel = 'before: no match';
endif;

Nothing here is wrong syntactically, but a reader has to already know that 'A' means “active” to understand the intent. Naming the value changes that:

if status = StatusActive;
   afterLabel = 'after: match';
else;
   afterLabel = 'after: no match';
endif;
Before, if status equals the literal quote A quote leaves a reader asking what A means. After naming the value with DCL-C StatusActive quote A quote, the comparison reads if status equals StatusActive, and the intent is visible where the comparison happens.
A readability transformation, not a compiler requirement or a performance claim.

Both comparisons behave identically — StatusActive is bound to 'A', so status = StatusActive and status = 'A' test the same thing. The difference is entirely for the reader: StatusActive states what the value means at the point where it is used, instead of forcing a reader to go find the definition (or guess).

Practical guidance, not an IBM rule: a repeated or unexplained literal like this is often called a magic value — a value whose meaning is not obvious from where it appears. Good candidates for a named constant include status codes, thresholds, limits, and any value that shows up in more than one place or that would need a comment to explain. This is an editorial judgment about your specific code, not something the compiler enforces or checks.

When a Literal Is Fine

Not every literal is a magic value, and turning every literal into a named constant is its own kind of clutter. A loop increment of 1, an obvious comparison to zero, or a genuinely one-off value that means exactly what it says rarely benefits from a name. If naming a literal would only restate what the literal already says — dcl-c One const(1); adds a name without adding meaning — it is reasonable to leave it as a literal.

The judgment call is whether a future reader (including you, later) would have to stop and ask what the value means. If the answer is no, a literal is fine. If the answer is yes, or if the same value needs to stay consistent across several places in the source, a named constant is worth the extra line.

Existing-Code Recognition

Constants can also appear in fixed-format source. IBM’s definition-specification rules identify the type of a definition by the entry in positions 24 through 25: a blank identifies a data-structure subfield or parameter, C identifies a named constant, and other letters identify data structures, prototypes, procedure interfaces, and standalone fields.3

IBM’s own sample definitions include exactly this kind of line:

D SpcSiz          C                   8

Positions 24-25 hold C, marking SpcSiz as a named constant with the value 8 — the fixed-format equivalent of a modern declaration.3 Written in free-form, the same constant is:

dcl-c SpcSiz 8;

For recognition purposes, that is the entire mapping: find the C in the type-entry column, then read the value in the keyword area the same way you would read the value on a DCL-C line. This lesson does not go further into fixed-format column authoring; see RPGLE Specifications: Fixed, Free, and Fully Free for that broader comparison.

Common Mistakes

Calling a constant “a variable that shouldn’t be changed.” A DCL-C named constant is never a variable in the first place — it has no storage the way a DCL-S field does. Describing it as a restricted variable blurs a distinction the language actually enforces.

Saying a literal or a constant “has no type.” IBM’s own wording is narrower: a numeric named constant has no predefined precision; its precision comes from context. That is different from having no type at all.

Treating *ON/*OFF as generic character values. They are documented figurative constants restricted to character fields — useful and idiomatic for indicators, but not a substitute for an arbitrary character literal everywhere.

Assuming a figurative constant applies to any field type. *BLANK/*BLANKS is for character, graphic, or UCS-2 fields; *HIVAL/*LOVAL and *ZERO/*ZEROS behave differently for character-family fields than for numeric fields. Check the field type before reusing a figurative constant from a different context.

Borrowing date-literal syntax from SQL. RPGLE’s D'...', T'...', and Z'...' typed literals are native RPG notation with their own format rules tied to DATFMT/TIMFMT; they are not SQL date literals and should not be assumed to follow SQL’s formatting rules.

Turning every literal into a named constant. Naming a self-explanatory, one-off value like a loop’s 1 increment adds a line without adding clarity. Reserve named constants for values that genuinely need a stable, reusable name.

Presenting the magic-value guidance as a compiler rule. Nothing in RPGLE requires a named constant. The recommendation is about readability and maintenance, and it is always a judgment call for the code in front of you.

FAQ

What is the difference between a variable, a constant, and a literal in RPGLE?

A variable (DCL-S) is named storage that may change. A named constant (DCL-C) is a name bound once to a fixed value. A literal is a value written directly in source code, with no name and no storage of its own.

How do I declare a named constant with DCL-C?

Write DCL-C, the constant’s name, and its value, ending with a semicolon. The value can be written directly (dcl-c StatusActive 'A';) or wrapped in CONST (dcl-c StatusActive const('A');) — IBM documents both as equivalent.1

Does a named constant have a type?

Not in the sense of a DCL-S type keyword — there is no CHAR or PACKED clause on a DCL-C line. A numeric named constant specifically has no predefined precision; its precision is determined by the context in which it is used.3

Does RPGLE have a native way to write a date literal?

Yes. A date literal is written D'xx-xx-xx', matching the format set by the DATFMT control-specification keyword. Time and timestamp literals use the analogous T'...' and Z'...' forms. None of these borrow from SQL syntax.3

What do ON and OFF mean, and where can I use them?

*ON represents all ones (character '1'); *OFF represents all zeros (character '0'). IBM documents both as valid only for character fields, which is why they work for indicators such as *INLR.2

What do HIVAL and LOVAL mean for character versus numeric fields?

For character, graphic, or UCS-2 fields, *HIVAL/*LOVAL are the highest/lowest collating characters. For numeric fields, they are the maximum and minimum values the field’s declared size and sign can represent.2

When should a literal become a named constant?

When a future reader would need to stop and ask what the value means, or when the same value needs to stay consistent in more than one place. This is editorial guidance, not an IBM requirement.

Is it ever fine to leave a literal as-is?

Yes. A self-explanatory, one-off value — a loop increment of 1, an obvious comparison to zero — rarely benefits from a name that would only restate what the literal already says.

How do older constant declarations map to modern DCL-C?

In fixed-format source, a C in the definition-type entry (positions 24-25) identifies a named constant, with its value in the keyword area. The modern equivalent is an ordinary DCL-C name value; line.3

Key Takeaways

  • A variable may change, a named constant is bound once, and a literal has no name at all — keep the three separate in your own explanations of code.
  • DCL-C name value; and DCL-C name const(value); mean the same thing; use whichever reads more clearly.
  • Character literals use apostrophes and double them for an embedded apostrophe; numeric literals never use apostrophes; typed literals (D'...', T'...', Z'...') are RPGLE’s own notation, not SQL’s.
  • Figurative constants are predefined and restricted to specific field types — *ON/*OFF to character fields, *BLANK/*BLANKS to character-family fields, *HIVAL/*LOVAL/*ZERO to character or numeric fields depending on type.
  • A numeric named constant has no predefined precision of its own; context supplies it.
  • Naming a magic value is a readability choice you make deliberately, not a rule the compiler enforces, and not every literal needs a name.

Continue Your Learning

  1. Foundation: RPGLE Variables and Storage Types
  2. Previous: RPGLE Data Structures Explained
  3. Current: RPGLE Constants and Literals
  4. Planned next: RPGLE Passing Data by Value and by Reference (ARTICLE-063)
  5. Then planned: RPGLE IF, ELSE, and ELSEIF Decisions (ARTICLE-064)
  6. Type context: RPGLE Data Types, Lengths, and Precision
  7. Learning-path overview: RPGLE for Beginners: A Practical IBM i Learning Path

Upcoming lessons are named without links because their public destinations have not been established for this draft. ARTICLE-063 covers how constants, literals, and variables move into and out of procedures; ARTICLE-064 covers the full IF/ELSE syntax that this article’s examples used only to illustrate a comparison.

IBM Evidence Used

The technical claims in this article are drawn from the IBM i 7.5 ILE RPG Reference and its “Free-Form Named Constant Definition” and “Figurative Constants” pages. The named-constant syntax, the equivalence of the direct and CONST forms, character/hexadecimal/numeric literal rules, the D'...'/T'...'/Z'...' typed-literal notation, the numeric-constant precision-by-context statement, and the fixed-format C definition-type entry are each drawn directly from that reference. The figurative-constant table is limited to the six forms IBM documents as most broadly applicable to ordinary fields, with their exact documented field-type restrictions preserved rather than generalized.

The four code assets are original teaching material checked against those rules. They have not been compiled or run on IBM i in this workspace; expected observations require an IBM i verification pass. The code README records the source-access details and claim map, including the exact reference pages used.

References


  1. IBM, “Free-Form Named Constant Definition,” IBM i 7.5 ILE RPG Reference. ↩↩↩

  2. IBM, “Figurative Constants,” IBM i 7.5 ILE RPG Reference. ↩↩↩↩↩↩↩↩↩↩↩↩↩

  3. IBM, “IBM i: ILE RPG Reference,” Constants, Literals, Named Constants, Standalone Fields, and Definition Specifications sections, IBM i 7.5. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

References

  1. Free-Form Named Constant Definition — IBM
  2. IBM i: ILE RPG Reference — IBM
  3. Figurative Constants — IBM



Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top