An RPGLE array gives one name to an ordered collection of elements that share a definition. Instead of declaring score1, score2, score3, and score4, you can declare scores once, give it four positions, and select a particular value with a subscript such as scores(2). That model is useful whenever the program has a known number of similar values and the position of each value has meaning.
This cornerstone lesson covers fixed-size standalone arrays: declaring them with DIM, assigning and reading individual elements, respecting RPG’s one-based subscript range, and traversing every element with %ELEM. IBM documentation often discusses arrays and tables together, and DIM can define either. The examples here use modern fully free-form standalone arrays so the essential collection model stays clear.1
Varying-dimension arrays, arrays of data structures, searching, sorting, and the larger family of array built-in functions are intentionally deferred. First learn the three facts that make ordinary array code predictable: every element has the declared type, a fixed array has a known element count, and a valid position runs from 1 through that count.
Quick Summary
| Question | Fixed-size RPGLE answer |
|---|---|
| How is an array declared? | Add DIM(number) to a definition such as dcl-s scores packed(5:0) dim(4); |
| What does the number mean? | The number of elements in the array |
| How is one element selected? | Put a subscript in parentheses: scores(1) |
| What is the first valid position? | 1, not 0 |
| What is the last valid position? | The array’s element count, available as %ELEM(array) |
| What does each element store? | One value with the type, length, and other attributes declared for the array |
The reliable beginner pattern is therefore:
dcl-s itemValues packed(7:2) dim(5) inz(0);
dcl-s itemIndex int(10);
for itemIndex = 1 to %elem(itemValues);
// Read or change itemValues(itemIndex)
endfor;
DIM(5) establishes five positions. %ELEM(itemValues) returns that element count, so the loop bound remains connected to the declaration instead of repeating the literal 5 elsewhere.12
What an Array Represents
A scalar variable holds one value. An array holds several elements under one variable name. Those elements are ordered, and a subscript identifies which element an expression should use.
Consider four weekly quantities:
dcl-s weeklyUnits packed(5:0) dim(4) inz(0);
The name is weeklyUnits. The element definition is packed(5:0). The dimension is four. Conceptually, the declaration creates these addressable positions:
| Position | Element reference | Same declared element type? |
|---|---|---|
| 1 | weeklyUnits(1) | Yes |
| 2 | weeklyUnits(2) | Yes |
| 3 | weeklyUnits(3) | Yes |
| 4 | weeklyUnits(4) | Yes |
This is homogeneous storage: the declaration does not give position 1 one type and position 2 another. If a business item needs several related fields, that is a data-structure design question reserved for ARTICLE-074. An array is the simpler idea: repeat one element definition a known number of times.

Declaration Anatomy
The core fully free-form declaration has four useful parts:
dcl-s productCodes char(8) dim(6) inz('');
dcl-sdeclares a standalone variable.productCodesnames the collection.char(8)defines each element as an eight-character value.dim(6)defines six elements.inz('')supplies an initial value for the storage.
IBM defines the numeric argument to ordinary DIM as a zero-decimal compile-time value. It may be a literal, a named constant, or a built-in function whose value is known at compile time.1 For an introductory fixed array, a small literal dimension is usually the easiest form to read.
The element type should match the values the collection represents. For example:
dcl-s regionNames char(20) dim(4) inz('');
dcl-s dailyCounts int(10) dim(7) inz(0);
dcl-s taxRates packed(7:4) dim(3) inz(0);
Choosing character, integer, or packed decimal storage is ordinary type design. The RPGLE Variables and Storage Types foundation explains named typed storage in detail. DIM adds repetition to that existing variable model; it does not replace the need to choose an appropriate element type.

Accessing Individual Elements
Write the array name followed by a subscript in parentheses. The subscript can be a whole-number literal or a numeric variable with zero decimal positions. IBM documents the valid range as 1 through n, where n is the number of elements.3
productCodes(1) = 'A100';
productCodes(2) = 'B205';
selectedIndex = 2;
selectedCode = productCodes(selectedIndex);
The first two statements assign values to two separate elements. The last statement reads one element selected at runtime. The array remains one declared variable, but each indexed reference behaves like the selected element for an ordinary assignment or expression.
basic-array-declaration.rpgle demonstrates this directly with a four-element numeric array. array-element-access.rpgle uses a numeric variable to select one of three character elements.
Subscripts are one-based
RPG array positions begin at 1. For DIM(4), valid subscripts are 1, 2, 3, and 4βnot 0 through 3.3 This is a frequent mistake for developers arriving from languages whose arrays begin at zero.
| Declaration | First valid reference | Last valid reference | Invalid examples |
|---|---|---|---|
dim(4) | values(1) | values(4) | values(0), values(5) |
dim(7) | values(1) | values(7) | values(0), values(8) |
When a subscript comes from data or a calculation, validate it before using it:
if selectedIndex >= 1 and selectedIndex <= %elem(productCodes);
selectedCode = productCodes(selectedIndex);
endif;
The comparison makes both boundaries visible. It also continues to match the array if its fixed dimension changes later.
Processing Every Element
Arrays become most useful when one piece of logic applies to each position. A counted FOR loop expresses that traversal without hard-coding a separate statement for every element:
for amountIndex = 1 to %elem(orderAmounts);
orderTotal += orderAmounts(amountIndex);
endfor;
%ELEM returns the number of elements in an array or table.2 For the fixed-size array in this article, that value is the declared dimension. The loop starts at the first valid RPG subscript and ends at the last one.
readable-array-processing.rpgle declares five order amounts, assigns sample values, and totals them with this pattern. The example is deliberately in-memory. It does not invent a database file, external service, or runtime transcript.
The loop is supporting syntax, not a new loop lesson. Counted iteration was established in RPGLE DO Loops Explained. Here the new idea is how the loop index maps to the array’s valid positions.
Keep capacity and meaningful data separate
A fixed dimension tells you how many elements the array contains. It does not automatically tell you how many positions the application has filled with meaningful business values.
Suppose recentCodes has DIM(10), but the program has loaded only three codes. %ELEM(recentCodes) is still 10 because the fixed array contains ten elements. If only loaded entries should be processed, track that count separately and ensure it never exceeds the dimension:
for codeIndex = 1 to loadedCodeCount;
// Process only populated positions
endfor;
This distinction is application reasoning built on the fixed-size model. ARTICLE-073 will cover varying-dimension arrays, where the current element count can change.
Arrays and the Word “Table”
The canonical title includes both terms because IBM’s RPG reference continues to describe arrays and tables together. The DIM documentation explicitly says the keyword defines the number of elements in an array or table, and %ELEM accepts either name.12
For new code and for this beginner foundation, array is the clearest default term for indexed repeated storage. Older RPG code and documentation may use table in compile-time-data and table-lookup contexts. Recognize that vocabulary, but do not assume that a database table is meant. An RPG table in this language context is not automatically a Db2 table, physical file, or result set.
Loading compile-time table data, search operations, and sequence requirements would distract from the declaration-and-index model. They are outside this article’s examples. Array helper operations such as lookup, subset, and sort belong to ARTICLE-075.
Common Mistakes
Starting with subscript zero
For the fixed arrays shown here, the valid range begins at 1.3 A loop written from 0 to %ELEM(values) - 1 follows a zero-based convention from another language, not RPG’s documented one-based range.
Writing one past the end
If an array has DIM(4), position 5 is not part of that array. Use %ELEM for the upper boundary and validate externally supplied positions before indexing.
Repeating the dimension as a magic number
This loop works only while the declaration remains unchanged:
for itemIndex = 1 to 5;
This form states the real relationship:
for itemIndex = 1 to %elem(itemValues);
The preference for %ELEM is maintainability guidance. IBM supplies the built-in function and defines its result; choosing it as a loop bound makes the code’s dependency explicit.
Mixing unlike concepts in parallel arrays
Several arrays that must always share the same subscript can drift out of alignment. If customerNames(3), customerNumbers(3), and customerStatuses(3) jointly describe one customer, a related-field structure may express that model better. ARTICLE-074 owns that design discussion.
Treating capacity as a loaded count
%ELEM on a fixed array reports its element count, not the number of positions your application considers populated.2 Track a separate meaningful-entry count when those values differ.
Jumping to advanced operations too early
Searching and sorting are important, but they rely on a sound understanding of element type, dimension, order, and bounds. Keep the first examples focused on direct access and simple traversal. ARTICLE-075 will introduce the built-in-function toolkit after this foundation and ARTICLE-073’s varying-dimension model.
Readability Guidance
The following points are practical recommendations, not additional RPG language rules:
- Use a plural collection name such as
orderAmountsand a singular element-oriented index name such asamountIndex. - Keep the array declaration near its related count or index variables when their relationship is local and important.
- Prefer
%ELEM(arrayName)over a repeated numeric upper bound when the code intends to visit the entire fixed array. - Validate a calculated or externally supplied subscript before the array reference.
- Distinguish the array’s capacity from the number of meaningful entries with names such as
maximumCodesandloadedCodeCount. - Choose a data structure when one position must contain several differently typed related fields; do not force that model into parallel scalar arrays.
Practical Decision Rules
Use a fixed-size standalone array when all of these are true:
- The values share one element definition.
- Their order or position matters.
- The required capacity is known when the program is compiled.
- Individual positions or straightforward whole-array traversal solve the immediate problem.
Pause and choose a later topic when the requirement changes:
- If the current number of elements must grow or shrink, continue with ARTICLE-073.
- If each position represents a record with related fields, continue with ARTICLE-074.
- If the main task is searching, sorting, slicing, totaling, or other helpers, continue with ARTICLE-075.
- If values come from Db2 or native file I/O, use the later database-I/O lessons rather than treating an array as a database substitute.
Key Takeaways
DIM(n)gives an RPGLE array or tablenelements.1- Every element follows the array’s declared element definition.
- Parentheses select an element, and the valid fixed-array subscript range is 1 through the element count.3
%ELEM(array)returns the element count and provides a declaration-linked loop boundary.2- A fixed array’s capacity and the application’s meaningful-entry count are different concepts.
- Naming and boundary checks make indexed code easier to review, but those practices should remain clearly separated from IBM-defined semantics.
Related Learning Path
- Pillar: RPGLE for Beginners: A Practical IBM i Learning Path (ARTICLE-046)
- Prerequisite: RPGLE Variables and Storage Types (ARTICLE-059)
- Current cornerstone: RPGLE Arrays and Tables (ARTICLE-072)
- Recommended next: RPGLE Varying-Dimension Arrays (ARTICLE-073)
- Recommended next: RPGLE Data Structures for Related Fields (ARTICLE-074)
ARTICLE-073 and ARTICLE-074 are named from the canonical registry but remain unlinked until publishable repository routes exist.
IBM Evidence Used
IBM i 7.5 DIM documentation supports the element-count declaration model and the requirement that an ordinary numeric dimension be a zero-decimal compile-time value.1 IBM i 7.5 %ELEM documentation supports retrieving the number of elements in an array or table.2 IBM’s field-name reference supports parenthesized element selection and the valid subscript range from 1 through the number of elements.3
The corresponding IBM i 7.4 topics were checked for the same fixed-array model.456 The array examples and reasoned traces are documentation-reviewed; not compiled or run on IBM i in this workspace. Recommendations about naming, %ELEM as a maintainability boundary, parallel arrays, and placement are editorial guidance rather than IBM language rules.
References
IBM, DIM({AUTO:|CTDATA|*VAR:}numeric_constant), IBM i 7.5, accessed 2026-09-17. ↩↩↩↩↩↩
IBM, %ELEM (Get Number of Elements), IBM i 7.5, accessed 2026-09-17. ↩↩↩↩↩↩
IBM, Positions 49-62 (Field Name), IBM i 7.5, accessed 2026-09-17. ↩↩↩↩↩
IBM, DIM({AUTO:|CTDATA|*VAR:}numeric_constant), IBM i 7.4, accessed 2026-09-17. ↩
IBM, %ELEM (Get Number of Elements), IBM i 7.4, accessed 2026-09-17. ↩
IBM, Positions 49-62 (Field Name), IBM i 7.4, accessed 2026-09-17. ↩
References