REDEFINES, RENAMES and TYPEDEF
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; an edition 4 is upcoming, in DIS ballot), GnuCOBOL 3.2
(28 July 2023, the latest release) and IBM Enterprise COBOL for z/OS 6.5 (PTFs through September 2026), and was checked on
2026-10-20. Every portable example below was compiled with cobc -x -Wall (GnuCOBOL 3.2.0, fixed reference format) and run,
and the output and the diagnostics shown are real; where an example needs -std=ibm the text says so. The ISO standard is
paywalled and was not read: the rules for the standard come from the vendor manuals, which say where they follow it. Code
that only Enterprise COBOL accepts is labelled "z/OS; not run here" and was checked statement by statement against the
Language Reference.
A COBOL program describes storage once and then looks at it in several ways. This page covers the four Data Division
features that describe the same bytes more than once or control where they sit: REDEFINES (another description of an
area), RENAMES (a regrouping of existing items under a level-66 name), SYNCHRONIZED (alignment of binary items, and the
slack bytes it adds) and TYPEDEF/TYPE (a named description that is reused, with the STRONG variant of Enterprise COBOL
6.5 that makes the compiler check it). The level numbers, group items and FILLER that all of them rely on are in
Data Division and Level Numbers; the PICTURE and
USAGE clauses that decide what a description means are in The PICTURE Clause and
Usage and Numeric Representation. The
Circulation layouts (BOOKREC, LOANREC) are the ones used throughout the section.
REDEFINES
The REDEFINES clause lets several data description entries describe the same storage area (Enterprise COBOL Language
Reference, REDEFINES clause). Nothing is allocated or converted: both descriptions are in effect at all times, and the
program decides which one it uses at any point. The entry that introduces the area is the redefined item (the object,
data-name-2); the entry that carries the clause is the redefining item (the subject, data-name-1).
level-number data-name-1 REDEFINES data-name-2 (rest of the description)
level-number FILLER REDEFINES data-name-2
The rules
The rules below are from the Enterprise COBOL 6.5 Language Reference; the right-hand column notes what GnuCOBOL 3.2 does (each point was tried, and the diagnostics are shown later on this page).
| Rule (Enterprise COBOL 6.5) | GnuCOBOL 3.2.0 |
|---|---|
|
Same; the |
The redefining item and the redefined item have the same level in the hierarchy (the level numbers may differ). Neither may be level 66 or 88. |
Same. |
The redefined item may itself be a redefining item, but may not have an |
|
Neither the redefining item nor any item under it may have a |
|
Any usage is allowed on either side. |
Same. |
No entry with a lower level number may come between the two entries, and the redefinition ends at the next entry whose level number is equal to or lower than the redefining item. |
Same. A further item at the same level between the two entries is rejected: |
The redefining item may be larger than the redefined one, except for an |
Larger is an error by default ( |
Several redefinitions of one area are allowed, and each may name either the original entry or the previous redefinition. |
Naming the previous redefinition ( |
A |
Not applicable (see the |
Alternate views of one record
The classic use is one transaction area with a code that says which layout applies. The example gives the 30-byte
Circulation transaction three views: a loan or return (the LOANREC fields), a fine adjustment, and a free-text note. The
TRAN-CODE condition-names choose the view in an EVALUATE; the data is moved in as one literal for brevity.
IDENTIFICATION DIVISION.
PROGRAM-ID. RD1.
* One 30-byte transaction area, three alternate views.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TRAN-AREA.
05 TRAN-CODE PIC X.
88 TRAN-LOAN VALUE "O" "R".
88 TRAN-FINE-ADJ VALUE "F".
88 TRAN-NOTE VALUE "N".
05 TRAN-BODY PIC X(29).
05 LOAN-BODY REDEFINES TRAN-BODY.
10 LB-MEMBER-ID PIC 9(6).
10 LB-BOOK-ID PIC 9(6).
10 LB-DATE PIC 9(8).
10 FILLER PIC X(9).
05 FINE-BODY REDEFINES TRAN-BODY.
10 FB-MEMBER-ID PIC 9(6).
10 FB-AMOUNT PIC S9(5)V99.
10 FILLER PIC X(16).
05 NOTE-BODY REDEFINES TRAN-BODY.
10 NB-TEXT PIC X(29).
PROCEDURE DIVISION.
MOVE "O00010000000120261020" TO TRAN-AREA
PERFORM SHOW-TRAN
MOVE "F0001010001250" TO TRAN-AREA
PERFORM SHOW-TRAN
MOVE "NCard replaced at desk" TO TRAN-AREA
PERFORM SHOW-TRAN
DISPLAY "area is " LENGTH OF TRAN-AREA " bytes"
STOP RUN.
SHOW-TRAN.
EVALUATE TRUE
WHEN TRAN-LOAN
DISPLAY "loan member " LB-MEMBER-ID
" book " LB-BOOK-ID " date " LB-DATE
WHEN TRAN-FINE-ADJ
DISPLAY "fine member " FB-MEMBER-ID
" amount " FB-AMOUNT
WHEN TRAN-NOTE
DISPLAY "note " NB-TEXT
END-EVALUATE.
The output is:
loan member 000100 book 000001 date 20261020
fine member 000101 amount +00012.50
note Card replaced at desk
area is 30 bytes
The three views are laid over TRAN-BODY byte for byte; no MOVE copies anything between them. The fine amount reads
+00012.50 because GnuCOBOL’s default DISPLAY shows a signed field with its sign and decimal point; with -std=ibm the same
field prints as 0001250+, without the decimal point, which is closer to what z/OS shows. The FILLER items pad
a short view up to the size of the area, which is not required by the language but keeps the layouts the same length.
A numeric view and a character view
The same bytes often need to be read as a number and as characters: a date split into year, month and day, or an input
field that must be tested with IS NUMERIC before it is used as a number. A level-01 item can redefine another level-01
item, as long as the two are adjacent; here the copybook record LOAN-RECORD is given a second layout, and a price is
given a character view.
IDENTIFICATION DIVISION.
PROGRAM-ID. RD2.
* Two views of one field: numeric and character.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY LOANREC.
01 LOAN-DATE-PARTS REDEFINES LOAN-RECORD.
05 FILLER PIC X(13).
05 LDP-YEAR PIC 9(4).
05 LDP-MONTH PIC 99.
05 LDP-DAY PIC 99.
05 FILLER PIC X(9).
01 PRICE-AREA.
05 PRICE-NUM PIC 9(4)V99.
05 PRICE-TEXT REDEFINES PRICE-NUM PIC X(6).
PROCEDURE DIVISION.
MOVE "O00010000000120261020" TO LOAN-RECORD
DISPLAY "date " LOAN-DATE
DISPLAY "year " LDP-YEAR " month " LDP-MONTH
" day " LDP-DAY
MOVE 11 TO LDP-MONTH
DISPLAY "date " LOAN-DATE " after changing the month"
MOVE "12.50 " TO PRICE-TEXT
IF PRICE-NUM IS NUMERIC
DISPLAY "price is numeric: " PRICE-NUM
ELSE
DISPLAY "price text " PRICE-TEXT " is not numeric"
END-IF
MOVE "001250" TO PRICE-TEXT
IF PRICE-NUM IS NUMERIC
DISPLAY "price is numeric: " PRICE-NUM
END-IF
STOP RUN.
The output is:
date 20261020
year 2026 month 10 day 20
date 20261120 after changing the month
price text 12.50 is not numeric
price is numeric: 0012.50
Changing LDP-MONTH changed LOAN-DATE because they are the same bytes, which is the point and the danger of the clause.
The IS NUMERIC test is what makes the character view safe: text such as 12.50 ` is not a valid zoned decimal, and using
`PRICE-NUM in arithmetic without the test would be an error on z/OS (a data exception, S0C7, covered with the other
numeric traps in MOVE and Data Movement).
Several redefinitions of one area
One area may have any number of redefinitions. They may all name the original entry, or each may name the one before it
(the Language Reference shows both forms). The example uses both: B and C redefine A, and D redefines B. The D
form needs -std=ibm in GnuCOBOL 3.2.0, as the table above says.
IDENTIFICATION DIVISION.
PROGRAM-ID. MULT1.
* Several redefinitions of one area, one through a chain.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 REC.
05 A PIC 9999.
05 B REDEFINES A PIC 9V999.
05 C REDEFINES A PIC 99V99.
05 D REDEFINES B PIC 999V9.
01 SHOW-B PIC 9.999.
01 SHOW-C PIC 99.99.
01 SHOW-D PIC 999.9.
PROCEDURE DIVISION.
MOVE 1234 TO A
MOVE B TO SHOW-B
MOVE C TO SHOW-C
MOVE D TO SHOW-D
DISPLAY "A=" A " B=" SHOW-B " C=" SHOW-C " D=" SHOW-D
STOP RUN.
Compiled and run with -std=ibm, the output is:
A=1234 B=1.234 C=12.34 D=123.4
All four items hold the digits 1234; only the implied decimal point differs, which is why the numeric-edited receivers
SHOW-B, SHOW-C and SHOW-D print 1.234, 12.34 and 123.4.
Implicit redefinition under an FD
When more than one level-01 entry follows a file description (FD), each later record implicitly redefines the storage of
the first: the clause must not be written (Language Reference, REDEFINES clause). This is how a file with several
record layouts is declared, and it is why the program must test a record code before choosing a layout (the LOAN-TYPE
test here, or a record-type byte in a multi-record file). The example reads the Circulation LOANTRAN file and shows the
same record through the LOANREC layout and through a plain 30-character record.
IDENTIFICATION DIVISION.
PROGRAM-ID. FD1.
* Two level-01 records under one FD redefine each other
* implicitly: no REDEFINES clause is written.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LOANTRAN ASSIGN TO "LOANTRAN"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD LOANTRAN.
COPY LOANREC.
01 RAW-RECORD PIC X(30).
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
88 AT-END VALUE "Y".
PROCEDURE DIVISION.
OPEN INPUT LOANTRAN
READ LOANTRAN
AT END SET AT-END TO TRUE
END-READ
PERFORM UNTIL AT-END
DISPLAY "raw [" RAW-RECORD "]"
DISPLAY "type " LOAN-TYPE " member " LOAN-MEMBER-ID
READ LOANTRAN
AT END SET AT-END TO TRUE
END-READ
END-PERFORM
CLOSE LOANTRAN
STOP RUN.
The output is:
raw [O00010000000120261020 ]
type O member 000100
raw [O00010100000220261020 ]
type O member 000101
raw [R00010000000120261020 ]
type R member 000100
raw [O00010200000320261020 ]
type O member 000102
The file sections and the SELECT entry used here are explained in
File Concepts, SELECT and FD.
Redefining does not convert
REDEFINES never changes a bit. If the two descriptions use different usages, the program reads the same bytes as two
different values. The Language Reference gives the case of a two-digit DISPLAY item redefined as a binary item: adding
the first to a counter adds 8, and adding the second adds a number taken from the character bytes. The example repeats it
with neutral names and prints the bytes with FUNCTION HEX-OF.
IDENTIFICATION DIVISION.
PROGRAM-ID. RD3.
* Redefining changes the view, not the bits.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 B PIC 99 USAGE DISPLAY VALUE 8.
01 C REDEFINES B PIC S99 USAGE COMP-4.
01 A PIC S9(5) USAGE COMP-5 VALUE 0.
PROCEDURE DIVISION.
ADD B TO A
DISPLAY "after ADD B: " A
MOVE 0 TO A
ADD C TO A
DISPLAY "after ADD C: " A
DISPLAY "bytes of B: " FUNCTION HEX-OF(B)
DISPLAY "length of C: " LENGTH OF C
STOP RUN.
With GnuCOBOL’s default dialect the output is:
after ADD B: +0000000008
after ADD C: +0000000048
bytes of B: 3038
length of C: 1
Compiled with -std=ibm it is:
after ADD B: +0000000008
after ADD C: +0000012344
bytes of B: 3038
length of C: 2
The two runs differ because a PIC S99 USAGE COMP-4 item is one byte long in GnuCOBOL’s default dialect (the
binary-size option is 1-2-4-8) and two bytes long in Enterprise COBOL and in the -std=ibm dialect. In the default
run C sees only the first byte, 0x30, which is 48. In the -std=ibm run it sees 0x3038, which is 12344. On z/OS the
two bytes of the value 8 are the EBCDIC digits F0 F8, and the same binary item is the value -3848, which is the figure
the Language Reference quotes. One program, three answers: the redefined area is the same, and the result depends on the
character code, the size of the binary item and the dialect. A redefinition that crosses usages is therefore a
portability decision, not a harmless alias (the rules for each usage are in
Usage and Numeric Representation).
Moving between the two views
The Language Reference says the results are undefined if a redefining item is moved to the redefined item, or the redefined
item to the redefining item (MOVE B TO C when B REDEFINES C), because the sender and the receiver overlap. Move to
and from a separate work area instead. The INITIALIZE statement and the VALUE clause interact with redefinitions as
described in VALUE, INITIALIZE and Condition Names:
a VALUE may appear on the original item (and under a redefined group), never on the redefining item.
Pitfalls, with the diagnostics
The next program breaks three of the rules deliberately: a VALUE on a redefining item, a redefined item that is a table,
and a REDEFINES that is not next to its object (PAGE-OTHER sits in between).
IDENTIFICATION DIVISION.
PROGRAM-ID. BAD1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FINE-AREA.
05 FINE-NUM PIC S9(5)V99.
05 FINE-TEXT REDEFINES FINE-NUM PIC X(7) VALUE "0000000".
01 SLOT-TABLE.
05 SLOT PIC X(4) OCCURS 5 TIMES.
05 SLOT-ALL REDEFINES SLOT PIC X(20).
01 PAGE-AREA.
05 PAGE-NO PIC 9(3).
05 PAGE-HEAD REDEFINES PAGE-NO.
10 PH-HUNDREDS PIC 9.
10 PH-REST PIC 99.
05 PAGE-OTHER PIC X(5).
05 PAGE-LATE REDEFINES PAGE-NO PIC X(3).
PROCEDURE DIVISION.
STOP RUN.
Deliberately wrong. cobc -x -Wall reports two warnings and one error:
bad1.cob:7: warning: initial VALUE clause ignored for REDEFINES item 'FINE-TEXT' [-Winitial-value]
5 | 01 FINE-AREA.
6 | 05 FINE-NUM PIC S9(5)V99.
7 > 05 FINE-TEXT REDEFINES FINE-NUM PIC X(7) VALUE "0000000".
8 | 01 SLOT-TABLE.
9 | 05 SLOT PIC X(4) OCCURS 5 TIMES.
bad1.cob:10: warning: the original definition 'SLOT' should not have an OCCURS clause [-Wothers]
8 | 01 SLOT-TABLE.
9 | 05 SLOT PIC X(4) OCCURS 5 TIMES.
10 > 05 SLOT-ALL REDEFINES SLOT PIC X(20).
11 | 01 PAGE-AREA.
12 | 05 PAGE-NO PIC 9(3).
bad1.cob:17: error: REDEFINES must follow the original definition
15 | 10 PH-REST PIC 99.
16 | 05 PAGE-OTHER PIC X(5).
17 > 05 PAGE-LATE REDEFINES PAGE-NO PIC X(3).
18 | PROCEDURE DIVISION.
19 | STOP RUN.
The error is the one that stops the build; the two warnings are accepted in GnuCOBOL but are errors in Enterprise COBOL, so
a program that compiles here with them may not compile on z/OS. Treat every -Wall warning on a REDEFINES as a defect.
Size mismatch is the other trap. The same fragment of two sizes, compiled by default and with -std=ibm:
IDENTIFICATION DIVISION.
PROGRAM-ID. BIG1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 REC.
05 A PIC X(6).
05 B REDEFINES A PIC X(8).
PROCEDURE DIVISION.
DISPLAY LENGTH OF REC
STOP RUN.
Deliberately wrong for the default dialect. The default dialect rejects it:
big1.cob:7: error: larger REDEFINES used
5 | 01 REC.
6 | 05 A PIC X(6).
7 > 05 B REDEFINES A PIC X(8).
8 | PROCEDURE DIVISION.
9 | DISPLAY LENGTH OF REC
big1.cob:7: note: size of 'B' larger than size of 'A' [-Wdialect]
and -std=ibm accepts it with this warning, after which the program runs and prints 8, the length of the larger
redefining item, which is now the size of the whole record:
big1.cob:7: warning: larger REDEFINES used [-Wdialect]
5 | 01 REC.
6 | 05 A PIC X(6).
7 > 05 B REDEFINES A PIC X(8).
8 | PROCEDURE DIVISION.
9 | DISPLAY LENGTH OF REC
big1.cob:7: note: size of 'B' larger than size of 'A' [-Wdialect]
The Language Reference allows it for a non-EXTERNAL item: the redefining item may use more storage than the redefined one
(its example is a six-byte PIC X(6) redefined by a national PIC N(4) of eight bytes). It is almost always a mistake in
a record layout, because the group is no longer the length the file or the copybook says it is.
When not to use REDEFINES
Two modern alternatives avoid most of the risk:
-
Reference modification (
LOAN-RECORD(14:4)) reads a slice of a field without declaring a second layout. It has no name and no type, so it suits a one-off slice; a namedREDEFINESsuits a slice used in many places. -
A separate receiving item and a
MOVEorUNSTRINGmakes a copy with a defined conversion. It costs a copy but has no overlap.
REDEFINES remains the right tool for multi-record layouts and for an alphanumeric view of a field that must be validated,
as in the examples. In new code, prefer a TYPEDEF (below) for a layout that is repeated, so the redefinition is written
once.
RENAMES
The RENAMES clause, always written on a level-66 entry, gives a new name to one item or to a range of consecutive
elementary items in a record. The new item is an alternative, possibly overlapping, grouping; it occupies the same bytes
as the original items and has no storage of its own.
66 data-name-1 RENAMES data-name-2 [ THROUGH | THRU data-name-3 ]
The rules (Enterprise COBOL 6.5 Language Reference, RENAMES clause):
-
Level-66 entries follow the last data description entry of the record, before the next
01or77. A record may have several. They are written after the record they rename, and cannot rename a level-01, 77, 88 or another 66. -
data-name-2anddata-name-3name elementary or group items of that record, withoutOCCURS; no item between them may haveOCCURS DEPENDING ON. They may be qualified. They are different items. -
With
THRU, the new item is an alphanumeric group running from the start ofdata-name-2to the end ofdata-name-3;data-name-3must not start or end beforedata-name-2, and may not be wholly inside it. -
Without
THRU, the new item takes all the attributes ofdata-name-2: an elementary item stays elementary, with the samePICTUREandUSAGE. -
THROUGHandTHRUare equivalent.data-name-1can be qualified only by the level-01 name. -
A
TYPEDEFitem, or anything inside one, cannot be renamed, and aRENAMESentry cannot have theTYPE,TYPEDEFclauses.
The example gives the book record a key (BOOK-ID through BOOK-ISBN), a stock group, and a plain alias.
IDENTIFICATION DIVISION.
PROGRAM-ID. RN1.
* Level 66: alternative, overlapping groupings.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY BOOKREC.
66 BOOK-KEY RENAMES BOOK-ID THRU BOOK-ISBN.
66 BOOK-STOCK RENAMES BOOK-COPIES THRU BOOK-PRICE.
66 BOOK-ISBN-ALT RENAMES BOOK-ISBN.
PROCEDURE DIVISION.
MOVE 000001 TO BOOK-ID
MOVE "9780000000017" TO BOOK-ISBN
MOVE "A Small Guide to Rates" TO BOOK-TITLE
MOVE 3 TO BOOK-COPIES
MOVE 12.5 TO BOOK-PRICE
DISPLAY "key [" BOOK-KEY "]"
DISPLAY "stock [" BOOK-STOCK "]"
DISPLAY "alt [" BOOK-ISBN-ALT "]"
DISPLAY "lengths " LENGTH OF BOOK-KEY " "
LENGTH OF BOOK-STOCK " " LENGTH OF BOOK-ISBN-ALT
MOVE ALL "9" TO BOOK-KEY
DISPLAY "id now " BOOK-ID " isbn now " BOOK-ISBN
STOP RUN.
The output is:
key [0000019780000000017]
stock [003001250]
alt [9780000000017]
lengths 19 9 13
id now 999999 isbn now 9999999999999
BOOK-KEY is 19 bytes (6 for the id and 13 for the ISBN), BOOK-STOCK is 9 (copies and price) and the single-item rename has
the length and the PICTURE of the ISBN. Because a renamed group is alphanumeric, MOVE ALL "9" TO BOOK-KEY wrote nines
into the numeric id as well as into the ISBN, with no check: RENAMES does not validate what is written through the group.
The renamed group is also not a good receiver for numeric data, for the same reason as any alphanumeric group.
Source: Enterprise COBOL 6.5 Language Reference: RENAMES clause and GnuCOBOL Programmer’s Guide: RENAMES
Two rules were tried against cobc: the range written in the wrong order, and a level-66 entry that is not next to its record:
IDENTIFICATION DIVISION.
PROGRAM-ID. BAD2.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY BOOKREC.
66 BOOK-KEY RENAMES BOOK-ISBN THRU BOOK-ID.
66 BOOK-ALL RENAMES BOOK-RECORD.
01 OTHER-AREA PIC X.
66 BOOK-LATE RENAMES BOOK-ID.
PROCEDURE DIVISION.
STOP RUN.
Deliberately wrong. The diagnostics are:
bad2.cob:6: error: THRU item 'BOOK-ID' may not come before 'BOOK-ISBN'
4 | WORKING-STORAGE SECTION.
5 | COPY BOOKREC.
6 > 66 BOOK-KEY RENAMES BOOK-ISBN THRU BOOK-ID.
7 | 66 BOOK-ALL RENAMES BOOK-RECORD.
8 | 01 OTHER-AREA PIC X.
bad2.cob:9: error: 'BOOK-LATE' must immediately follow the record 'BOOK-RECORD'
7 | 66 BOOK-ALL RENAMES BOOK-RECORD.
8 | 01 OTHER-AREA PIC X.
9 > 66 BOOK-LATE RENAMES BOOK-ID.
10 | PROCEDURE DIVISION.
11 | STOP RUN.
The renaming of a level-01 record (66 BOOK-ALL RENAMES BOOK-RECORD, the second entry above) is not reported by GnuCOBOL
3.2.0: it compiles with and without -std=ibm and LENGTH OF BOOK-ALL is 60. Enterprise COBOL’s rule forbids it, so avoid
the construct in portable code. Level-66 is also an obsolete-looking feature in new code: most programs get the same result
with REDEFINES or reference modification. It still appears in mainframe copybooks, which is why a reader must know it.
SYNCHRONIZED
SYNCHRONIZED (abbreviated SYNC) asks the compiler to place a binary item on a natural storage boundary: two bytes
for a halfword, four for a word, eight for a doubleword. It is never required, and it can speed up arithmetic on some
hardware. It affects the position of the item, and therefore the layout of the record, never the item’s length (Language
Reference, SYNCHRONIZED clause).
SYNCHRONIZED [ LEFT | RIGHT ] SYNC is the short form
The rules:
-
It may be written on an elementary item or on a level-01 group (every elementary item below is then synchronized). With
OCCURS, each occurrence is synchronized. It cannot be combined with theTYPEclause. -
LEFTandRIGHTare syntax checked and do nothing, in Enterprise COBOL and in GnuCOBOL. -
For
DISPLAY,PACKED-DECIMAL,NATIONAL,UTF-8and floating-point (external) items the clause is syntax checked and has no effect.COMP-1is aligned on a fullword,COMP-2on a doubleword, pointers andINDEXfollow theLPoption, andCOMP-3,COMP-4andCOMP-5are treated likePACKED-DECIMALandBINARYrespectively. -
In the
WORKING-STORAGE SECTIONeach level-01 item starts on a doubleword boundary; in theFILE SECTIONthe compiler assumes level-01 records that contain synchronized items are doubleword aligned in the buffer. -
If the item is the first one under a
REDEFINESitem, the redefined area must already be properly aligned: the Language Reference’s example is a four-byte item redefined byPIC S9(9) BINARY SYNC, which needs the four-byte item to start on a fullword.
Slack bytes
To put a synchronized item on its boundary the compiler inserts unused slack bytes in front of it (and, for a table of
groups, at the end of each occurrence so that every occurrence is aligned). The Language Reference gives the algorithm: add
up the bytes of all the elementary items before the binary item (including slack already added) and divide by m, which is 2
for a binary item of up to four digits, 4 for five digits or more, 4 for COMP-1, indexes and pointers, and 8 for COMP-2. If the
remainder r is not zero, m - r slack bytes are added. Slack bytes are included in the size of the enclosing group. A
file may also need slack bytes between records when blocked records contain synchronized items; the program supplies them
with a trailing FILLER. Enterprise COBOL’s option RULES(NOSLACKBYTES) makes the compiler issue a warning wherever
SYNC forces slack bytes (the option is described in the Enterprise COBOL Programming Guide), which is a cheap way to find the records whose length is not
the sum of their fields.
The example reproduces the Language Reference record of three alphanumeric items (11 bytes) followed by three binary items. Without
SYNC the record is 19 bytes. With it, one slack byte goes before B-1 and two before B-2, and the group is 22 bytes. The
hex dump shows the slack bytes, because MOVE ALL "x" fills the whole group, slack included, with 78.
IDENTIFICATION DIVISION.
PROGRAM-ID. SY1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PLAIN-RECORD.
05 A-1 PIC X(5).
05 A-2 PIC X(3).
05 A-3 PIC X(3).
05 B-1 PIC S9999 USAGE COMP.
05 B-2 PIC S99999 USAGE COMP.
05 B-3 PIC S9999 USAGE COMP.
01 SYNC-RECORD.
05 A-1 PIC X(5).
05 A-2 PIC X(3).
05 A-3 PIC X(3).
05 B-1 PIC S9999 USAGE COMP SYNCHRONIZED.
05 B-2 PIC S99999 USAGE COMP SYNCHRONIZED.
05 B-3 PIC S9999 USAGE COMP SYNCHRONIZED.
PROCEDURE DIVISION.
DISPLAY "plain " LENGTH OF PLAIN-RECORD
DISPLAY "sync " LENGTH OF SYNC-RECORD
MOVE ALL "x" TO SYNC-RECORD
MOVE 1 TO B-1 OF SYNC-RECORD
MOVE 2 TO B-2 OF SYNC-RECORD
MOVE 3 TO B-3 OF SYNC-RECORD
DISPLAY FUNCTION HEX-OF(SYNC-RECORD)
STOP RUN.
The output is:
plain 19
sync 22
78787878787878787878787800017878000000020003
Reading the dump: eleven 78 bytes for the alphanumeric items, one 78 slack byte, 0001 for B-1, two 78 slack bytes, 00000002
for B-2 and 0003 for B-3. The sizes match the figures in the Language Reference (22 bytes).
A table of groups gets the end-of-occurrence slack bytes. Another Language Reference record, WORK-RECORD, with ten occurrences
of a group that holds two synchronized binary items, is 161 bytes and each occurrence is 16 bytes long (12 bytes of items, two
slack bytes before COMP-PAY and two at the end of the occurrence, which is what the manual’s figures show):
IDENTIFICATION DIVISION.
PROGRAM-ID. SY2.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WORK-RECORD.
05 WORK-CODE PIC X.
05 COMP-TABLE OCCURS 10 TIMES.
10 COMP-TYPE PIC X.
10 COMP-PAY PIC S9(4)V99 COMP SYNC.
10 COMP-HOURS PIC S9(3) COMP SYNC.
10 COMP-NAME PIC X(5).
PROCEDURE DIVISION.
DISPLAY LENGTH OF WORK-RECORD " " LENGTH OF COMP-TABLE(1)
MOVE ALL "x" TO WORK-RECORD
MOVE 1 TO COMP-PAY(1)
MOVE 2 TO COMP-HOURS(1)
DISPLAY FUNCTION HEX-OF(WORK-RECORD(1:17))
STOP RUN.
The output is:
161 16
7878787800000064000278787878787878
The 17 bytes shown are WORK-CODE (78), then the first occurrence: the type byte 78, two slack bytes 7878, COMP-PAY as 00000064 (the
value 1 with two implied decimals is stored as 100, hex 64), COMP-HOURS as 0002, and then the five bytes of COMP-NAME and the two end-of-occurrence slack bytes, all 78. Both of these
examples give the same sizes as the manual, but GnuCOBOL does not follow the algorithm everywhere:
IDENTIFICATION DIVISION.
PROGRAM-ID. SY3.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 R1.
05 A PIC X.
05 B PIC S9(10) COMP SYNC.
01 R2.
05 A PIC X.
05 B PIC S9(10) COMP-5 SYNC.
01 R3.
05 A PIC X.
05 B PIC S9(4) COMP-3 SYNC.
01 R4.
05 A PIC X.
05 B COMP-1 SYNC.
PROCEDURE DIVISION.
DISPLAY LENGTH OF R1 " " LENGTH OF R2 " " LENGTH OF R3
" " LENGTH OF R4
STOP RUN.
16 16 4 8
The four records are one X byte plus a synchronized item. A ten-digit binary item (eight bytes) is aligned on an
eight-byte boundary in GnuCOBOL (7 slack bytes, length 16, for both COMP and COMP-5), whereas the algorithm above, which uses m = 4
for items of five digits or more, would give 12 bytes (not run here, since the Language Reference algorithm is
for z/OS). A packed-decimal item is ignored (4 bytes) and COMP-1 is aligned on a word (3 slack bytes, length 8), as in Enterprise
COBOL. Copybooks that mix SYNC with records written by other systems must therefore be checked on each compiler rather than
trusted.
When to use SYNC
For data that leaves the program, SYNC is a liability: records on files, in messages and in database columns have a fixed
byte layout, and slack bytes make that layout depend on the compiler. Leave it out of copybooks that describe external
records. Where it is used (in internal tables and work areas, to make binary arithmetic faster), measure first, because the
effect depends on the hardware and on options such as TRUNC and ARCH; the section’s page on performance and compiler options returns to the subject, and the TRUNC options that matter more for binary items are described in
Usage and Numeric Representation.
TYPEDEF and TYPE
TYPEDEF creates a named description that can be reused with the TYPE clause, so that a layout such as a date or an amount is written
once. COBOL 2002 is the origin of the feature in the standard, and Enterprise COBOL for z/OS has had it since 6.5 (the
Language Reference documents it, and the PTF PH73209 of September 2026 added the STRONG form). GnuCOBOL 3.2.0 accepts
TYPEDEF and TYPE too, although its Programmer’s Guide still lists TYPEDEF as a word that is not implemented (see
the table at the end of this section).
level-number type-name TYPEDEF [ STRONG ] (description of the type)
level-number data-name TYPE [ TO ] type-name [ OCCURS ... | VALUE ... ]
A type definition allocates no storage. An item defined with TYPE type-name takes the attributes of the type (the same
PICTURE, USAGE, group structure and subordinate names), and every item below a group type keeps its name.
Rules (Enterprise COBOL 6.5)
-
A
TYPEDEFmay be an elementary item or a group. It may appear in theWORKING-STORAGE,LOCAL-STORAGE,LINKAGEorFILEsections, or in the optionalTYPE SECTION, which comes first in the Data Division. In theTYPE SECTIONevery level-01 entry must haveTYPEDEF. -
A type must be defined before it is used (no forward reference) and may not contain a
TYPEclause that refers to itself, directly or indirectly. The scoping rules of type names are like those of data names. -
The
TYPEclause cannot be used in the same entry asPICTURE,USAGE,JUSTIFIED,BLANK WHEN ZERO,SIGN,SYNCHRONIZED,DYNAMICorRENAMES. It can be combined withOCCURS,VALUE,GLOBAL,EXTERNALandVOLATILE. It can appear withTYPEDEF(to define a type from another type, for instance a table). -
The subject of a
TYPEclause cannot be followed by subordinate entries. For an elementary type, level-88 condition-names go in the type definition, not under the instances. -
A
VALUEon the instance overrides theVALUEin the type at the same level. ATYPEDEFitem cannot be redefined or renamed (items inside a group type can be redefined, and the redefinition becomes part of the type), cannot haveEXTERNAL,VOLATILEorRENAMES, and the dependency object of anOCCURS DEPENDING ONin a group type cannot be inside the same type. -
A subordinate item can use
TYPEwith a level number as high as 49, as long as the whole item still has at most 49 levels. -
Enterprise COBOL adds qualification with
::(for instanceINCOMING::PARTS(1)orWORK-AREA::NAME) for items inside type instances and for index names; plainOFqualification still works.
An example that runs on GnuCOBOL
The example defines an elementary amount type, a date group type and a status type with two condition-names, then uses
them in a loan row and in a table. It shows the instance VALUE clause, the 88-levels carried by the type and OCCURS on a
type instance. It compiles with no warnings by default.
IDENTIFICATION DIVISION.
PROGRAM-ID. TY2.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MONEY-T TYPEDEF PIC S9(5)V99.
01 DATE-T TYPEDEF.
05 DT-YEAR PIC 9(4).
05 DT-MONTH PIC 99.
05 DT-DAY PIC 99.
01 STATUS-T TYPEDEF PIC X.
88 ST-ACTIVE VALUE "A".
88 ST-GONE VALUE "W".
01 LOAN-ROW.
05 LR-DUE TYPE DATE-T.
05 LR-FINE TYPE MONEY-T VALUE 1.25.
05 LR-ST TYPE STATUS-T.
01 DATE-LIST TYPE DATE-T OCCURS 3 TIMES.
PROCEDURE DIVISION.
MOVE 20261105 TO LR-DUE
MOVE 1 TO DT-MONTH OF DATE-LIST(2)
SET ST-ACTIVE TO TRUE
DISPLAY LR-DUE " " DT-YEAR OF LR-DUE " " LR-FINE " " LR-ST
DISPLAY LENGTH OF LOAN-ROW " " LENGTH OF DATE-LIST
STOP RUN.
The output is:
20261105 2026 +00001.25 A
16 8
LOAN-ROW is 16 bytes (8 for the date, 7 for the fine, 1 for the status). LENGTH OF DATE-LIST is 8, the length of one
table entry, because LENGTH OF a table name gives the length of a single occurrence; the table has three of them, 24
bytes in all. The fine was initialised by the instance VALUE, and SET ST-ACTIVE
TO TRUE set the 88-level that came from STATUS-T. The same source with -std=ibm also compiles, with the DISPLAY format difference seen
before.
Where GnuCOBOL 3.2 stops
Four limits were found by compiling. The first program breaks the TYPE rules (a PICTURE on a TYPE entry, an undefined
type, an entry below a TYPE item, and a REDEFINES of a type name).
IDENTIFICATION DIVISION.
PROGRAM-ID. TY5.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DATE-T TYPEDEF.
05 DT-YEAR PIC 9(4).
05 DT-MONTH PIC 99.
01 LR-DUE TYPE DATE-T.
01 BAD-ONE TYPE DATE-T PIC X(6).
01 BAD-TWO TYPE NO-SUCH-T.
01 DATE-X REDEFINES DATE-T PIC X(6).
01 LR-OVR TYPE DATE-T.
05 EXTRA PIC X.
PROCEDURE DIVISION.
STOP RUN.
Deliberately wrong. The diagnostics are:
ty5.cob:9: error: illegal combination of TYPE TO with other clauses
7 | 05 DT-MONTH PIC 99.
8 | 01 LR-DUE TYPE DATE-T.
9 > 01 BAD-ONE TYPE DATE-T PIC X(6).
10 | 01 BAD-TWO TYPE NO-SUCH-T.
11 | 01 DATE-X REDEFINES DATE-T PIC X(6).
ty5.cob:10: error: 'NO-SUCH-T' is not defined
8 | 01 LR-DUE TYPE DATE-T.
9 | 01 BAD-ONE TYPE DATE-T PIC X(6).
10 > 01 BAD-TWO TYPE NO-SUCH-T.
11 | 01 DATE-X REDEFINES DATE-T PIC X(6).
12 | 01 LR-OVR TYPE DATE-T.
ty5.cob:13: error: entry following TYPE TO may not be subordinate to it
11 | 01 DATE-X REDEFINES DATE-T PIC X(6).
12 | 01 LR-OVR TYPE DATE-T.
13 > 05 EXTRA PIC X.
14 | PROCEDURE DIVISION.
15 | STOP RUN.
ty5.cob:11: error: REDEFINES must follow the original definition
9 | 01 BAD-ONE TYPE DATE-T PIC X(6).
10 | 01 BAD-TWO TYPE NO-SUCH-T.
11 > 01 DATE-X REDEFINES DATE-T PIC X(6).
12 | 01 LR-OVR TYPE DATE-T.
13 | 05 EXTRA PIC X.
The other limits are in the TYPE SECTION and :: qualification, which Enterprise COBOL has and GnuCOBOL 3.2.0 does not:
IDENTIFICATION DIVISION.
PROGRAM-ID. TY4.
DATA DIVISION.
TYPE SECTION.
01 MONEY-T TYPEDEF PIC S9(5)V99.
WORKING-STORAGE SECTION.
01 FINE-AMT TYPE MONEY-T.
PROCEDURE DIVISION.
STOP RUN.
Deliberately wrong for GnuCOBOL (the same source is valid in Enterprise COBOL). The first diagnostics are:
ty4.cob:4: error: PROCEDURE DIVISION header missing
2 | PROGRAM-ID. TY4.
3 | DATA DIVISION.
4 > TYPE SECTION.
5 | 01 MONEY-T TYPEDEF PIC S9(5)V99.
6 | WORKING-STORAGE SECTION.
ty4.cob:4: error: syntax error, unexpected TYPE
ty4.cob:5: error: syntax error, unexpected Identifier, expecting SECTION or .
3 | DATA DIVISION.
4 | TYPE SECTION.
5 > 01 MONEY-T TYPEDEF PIC S9(5)V99.
6 | WORKING-STORAGE SECTION.
7 | 01 FINE-AMT TYPE MONEY-T.
ty4.cob:5: note: unknown statement '01'
ty4.cob:6: error: syntax error, unexpected WORKING-STORAGE
4 | TYPE SECTION.
5 | 01 MONEY-T TYPEDEF PIC S9(5)V99.
6 > WORKING-STORAGE SECTION.
7 | 01 FINE-AMT TYPE MONEY-T.
8 | PROCEDURE DIVISION.
ty4.cob:7: error: syntax error, unexpected Identifier, expecting SECTION or .
5 | 01 MONEY-T TYPEDEF PIC S9(5)V99.
6 | WORKING-STORAGE SECTION.
7 > 01 FINE-AMT TYPE MONEY-T.
8 | PROCEDURE DIVISION.
9 | STOP RUN.
ty4.cob:7: note: unknown statement '01'
ty4.cob:8: error: syntax error, unexpected PROCEDURE
6 | WORKING-STORAGE SECTION.
7 | 01 FINE-AMT TYPE MONEY-T.
8 > PROCEDURE DIVISION.
9 | STOP RUN.
10 | <EOF>
IDENTIFICATION DIVISION.
PROGRAM-ID. TY6.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DATE-T TYPEDEF.
05 DT-YEAR PIC 9(4).
05 DT-MONTH PIC 99.
01 LR-DUE TYPE DATE-T.
PROCEDURE DIVISION.
MOVE 2026 TO LR-DUE::DT-YEAR
STOP RUN.
Deliberately wrong for GnuCOBOL (valid Enterprise COBOL syntax). The diagnostics are:
ty6.cob:10: warning: alphanumeric value is expected [-Wtyping]
8 | 01 LR-DUE TYPE DATE-T.
9 | PROCEDURE DIVISION.
10 > MOVE 2026 TO LR-DUE::DT-YEAR
11 | STOP RUN.
12 | <EOF>
ty6.cob:8: note: 'LR-DUE' defined here as a group of length 6 [-Wtyping]
6 | 05 DT-YEAR PIC 9(4).
7 | 05 DT-MONTH PIC 99.
8 > 01 LR-DUE TYPE DATE-T.
9 | PROCEDURE DIVISION.
10 | MOVE 2026 TO LR-DUE::DT-YEAR
ty6.cob:10: error: syntax error, unexpected :
8 | 01 LR-DUE TYPE DATE-T.
9 | PROCEDURE DIVISION.
10 > MOVE 2026 TO LR-DUE::DT-YEAR
11 | STOP RUN.
12 | <EOF>
Under GnuCOBOL the qualified reference must be written DT-YEAR OF LR-DUE. Two dialect details were also found: -std=ibm-strict
and -std=cobol85 reject TYPEDEF altogether (a syntax error on the word), and with -std=cobol2002 or -std=cobol2014 a type instance with
OCCURS at level 01 (as in the example) is reported as 01/77 OCCURS does not conform.
STRONG types (Enterprise COBOL 6.5, PTF PH73209)
A type declared TYPEDEF STRONG is a strong type; its instances are strongly-typed items, and the compiler checks how they are
used. A type without STRONG is a weak type and behaves like the plain group it expands to. The rules, from the Language
Reference as documented for 6.5 (the strong form needs the PTF named above):
-
STRONGis allowed only on a group type. The group, and every group below it, cannot have aVALUEclause or be a condition variable. -
Items inside a strong type cannot be redefined (implicitly or explicitly), renamed in whole or in part, or reference-modified (except elementary alphabetic, alphanumeric, UTF-8 and national items inside it).
-
A strongly-typed group can be compared only with another group of the same type, and as a receiving item only in the contexts the manual lists: parameters and returning items,
INITIALIZE,JSON PARSE,MOVE,READ, and theFROMphrase ofRELEASE,REWRITEandWRITE, plusRETURN. -
In a
MOVE, the sender must be an instance of the same type; forWRITE,REWRITEandRELEASEwithFROM, theFROMitem must be of the same type as the record. -
In a
CALL, strongly-typed items can only be passedBY CONTENT.
A z/OS sketch of the Circulation key; z/OS; not run here. The two instances can be moved and compared with each other, and the last two statements are the compile-time errors the strong type exists to produce (the message numbers are not quoted because they were not checked):
01 LOAN-KEY-T TYPEDEF STRONG.
05 LK-MEMBER-ID PIC 9(6).
05 LK-BOOK-ID PIC 9(6).
01 KEY-A TYPE LOAN-KEY-T.
01 KEY-B TYPE LOAN-KEY-T.
01 RAW-KEY PIC X(12).
...
MOVE KEY-A TO KEY-B
IF KEY-A = KEY-B
DISPLAY "same key"
END-IF
MOVE RAW-KEY TO KEY-A
IF KEY-A = RAW-KEY
DISPLAY "never reached"
END-IF
Source: Enterprise COBOL 6.5 Language Reference: TYPEDEF clause and What’s new in Enterprise COBOL for z/OS 6.5
GnuCOBOL 3.2.0 recognizes the word but does not implement it. The compiler accepts the strong type as a weak one and says so:
IDENTIFICATION DIVISION.
PROGRAM-ID. TY3.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DATE-T TYPEDEF STRONG.
05 DT-YEAR PIC 9(4).
05 DT-MONTH PIC 99.
05 DT-DAY PIC 99.
01 D1 TYPE DATE-T.
PROCEDURE DIVISION.
MOVE "20261105" TO D1
STOP RUN.
Deliberately warns. The diagnostic is:
ty3.cob:5: warning: TYPEDEF STRONG is not implemented [-Wpending]
3 | DATA DIVISION.
4 | WORKING-STORAGE SECTION.
5 > 01 DATE-T TYPEDEF STRONG.
6 | 05 DT-YEAR PIC 9(4).
7 | 05 DT-MONTH PIC 99.
The program compiles and runs; the MOVE of a literal into the strong group, which Enterprise COBOL would reject, is
accepted. A portable program must not rely on strong checking, and a program that does must be compiled on z/OS.
Support at a glance
| Feature | ISO/IEC 1989:2023 | Enterprise COBOL 6.5 | GnuCOBOL 3.2.0 |
|---|---|---|---|
|
Yes |
Yes |
Yes, with a stricter size and chain policy in the default dialect |
|
Yes |
Yes |
Yes |
|
Yes |
Yes, with the slack-byte algorithm |
Yes, but eight-byte items are eight-byte aligned |
|
Yes (introduced in COBOL 2002) |
Yes (6.5) |
Accepted; no |
|
No (an IBM feature, as far as the sources read here show) |
Yes (PTF PH73209, September 2026) |
Accepted with a warning, not enforced |
The standard column rests on the vendor documentation and the history page, because the standard itself was not read. The 2023 edition and the upcoming edition are described in History and Standards, and the dialects in Compilers and Dialects.
Where the book is outdated
The book consulted for this section (Taulli, Modern Mainframe Development, 2022) introduces REDEFINES in its data-types chapter;
nothing is copied from it. Four points need correcting or updating when it is read today:
-
Its
REDEFINESsample carries a strayPICTUREkeyword between the clause and the redefined name, and the size of the redefining item does not match the seven-character edited item it redefines. The correct form isREDEFINES data-name PICTURE ...with the keyword after the name, and a redefining item should have the length of the redefined item (or document why not). -
The book says binary items are not good for arithmetic because of rounding differences. Binary integers are exact. The real issues are truncation under the
TRUNCoption and decimal scaling, which also decide what aREDEFINESof a binary item sees, as the example above shows. -
RENAMES,SYNCHRONIZEDand slack bytes are legacy layout tools that the book does not cover, andTYPEDEF/TYPE(Enterprise COBOL 6.5) andSTRONGtypes (PTF PH73209) are newer than the book. -
Examples written for 2022-era compilers show
REDEFINESas the way to build every table or variant record. WithTYPEDEF, reference modification andOCCURS(in Tables and OCCURS) it is only one of the tools.
References
-
Enterprise COBOL for z/OS 6.5 Language Reference: REDEFINES clause
-
Enterprise COBOL for z/OS 6.5 Language Reference: RENAMES clause
-
Enterprise COBOL for z/OS 6.5 Language Reference: SYNCHRONIZED clause
-
Enterprise COBOL for z/OS 6.5 Language Reference: TYPEDEF clause
-
Enterprise COBOL for z/OS 6.5 Language Reference: TYPE clause
-
Modern Mainframe Development (Tom Taulli, O’Reilly Media, 2022), consulted as a narrative