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

REDEFINES must be the first clause after the data name (or FILLER), or after the level number if the name is omitted.

Same; the free-redefines-position dialect option controls the strictness.

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 OCCURS clause (it may be inside a table, if the reference is not subscripted). Neither item may have OCCURS DEPENDING ON.

OCCURS on the object is accepted with a warning (should not have an OCCURS clause).

Neither the redefining item nor any item under it may have a VALUE clause.

VALUE on a redefining item compiles with the warning initial VALUE clause ignored.

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: REDEFINES must follow the original definition.

The redefining item may be larger than the redefined one, except for an EXTERNAL record.

Larger is an error by default (larger REDEFINES used) and a warning with -std=ibm. For a level-01 item it is a warning (-Wlarger-01-redefines).

Several redefinitions of one area are allowed, and each may name either the original entry or the previous redefinition.

Naming the previous redefinition (D REDEFINES B) is an error by default ('B' is not the original definition) and is accepted with -std=ibm.

A TYPEDEF item cannot be redefined, but items inside a group type definition can be.

Not applicable (see the TYPEDEF section): the typedef name has no storage in GnuCOBOL either.

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 named REDEFINES suits a slice used in many places.

  • A separate receiving item and a MOVE or UNSTRING makes 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 01 or 77. 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-2 and data-name-3 name elementary or group items of that record, without OCCURS; no item between them may have OCCURS DEPENDING ON. They may be qualified. They are different items.

  • With THRU, the new item is an alphanumeric group running from the start of data-name-2 to the end of data-name-3; data-name-3 must not start or end before data-name-2, and may not be wholly inside it.

  • Without THRU, the new item takes all the attributes of data-name-2: an elementary item stays elementary, with the same PICTURE and USAGE.

  • THROUGH and THRU are equivalent. data-name-1 can be qualified only by the level-01 name.

  • A TYPEDEF item, or anything inside one, cannot be renamed, and a RENAMES entry cannot have the TYPE, TYPEDEF clauses.

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.

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 the TYPE clause.

  • LEFT and RIGHT are syntax checked and do nothing, in Enterprise COBOL and in GnuCOBOL.

  • For DISPLAY, PACKED-DECIMAL, NATIONAL, UTF-8 and floating-point (external) items the clause is syntax checked and has no effect. COMP-1 is aligned on a fullword, COMP-2 on a doubleword, pointers and INDEX follow the LP option, and COMP-3, COMP-4 and COMP-5 are treated like PACKED-DECIMAL and BINARY respectively.

  • In the WORKING-STORAGE SECTION each level-01 item starts on a doubleword boundary; in the FILE SECTION the compiler assumes level-01 records that contain synchronized items are doubleword aligned in the buffer.

  • If the item is the first one under a REDEFINES item, the redefined area must already be properly aligned: the Language Reference’s example is a four-byte item redefined by PIC 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 TYPEDEF may be an elementary item or a group. It may appear in the WORKING-STORAGE, LOCAL-STORAGE, LINKAGE or FILE sections, or in the optional TYPE SECTION, which comes first in the Data Division. In the TYPE SECTION every level-01 entry must have TYPEDEF.

  • A type must be defined before it is used (no forward reference) and may not contain a TYPE clause that refers to itself, directly or indirectly. The scoping rules of type names are like those of data names.

  • The TYPE clause cannot be used in the same entry as PICTURE, USAGE, JUSTIFIED, BLANK WHEN ZERO, SIGN, SYNCHRONIZED, DYNAMIC or RENAMES. It can be combined with OCCURS, VALUE, GLOBAL, EXTERNAL and VOLATILE. It can appear with TYPEDEF (to define a type from another type, for instance a table).

  • The subject of a TYPE clause cannot be followed by subordinate entries. For an elementary type, level-88 condition-names go in the type definition, not under the instances.

  • A VALUE on the instance overrides the VALUE in the type at the same level. A TYPEDEF item cannot be redefined or renamed (items inside a group type can be redefined, and the redefinition becomes part of the type), cannot have EXTERNAL, VOLATILE or RENAMES, and the dependency object of an OCCURS DEPENDING ON in a group type cannot be inside the same type.

  • A subordinate item can use TYPE with 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 instance INCOMING::PARTS(1) or WORK-AREA::NAME) for items inside type instances and for index names; plain OF qualification 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):

  • STRONG is allowed only on a group type. The group, and every group below it, cannot have a VALUE clause 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 the FROM phrase of RELEASE, REWRITE and WRITE, plus RETURN.

  • In a MOVE, the sender must be an instance of the same type; for WRITE, REWRITE and RELEASE with FROM, the FROM item must be of the same type as the record.

  • In a CALL, strongly-typed items can only be passed BY 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

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

REDEFINES (all rules above)

Yes

Yes

Yes, with a stricter size and chain policy in the default dialect

RENAMES (level 66)

Yes

Yes

Yes

SYNCHRONIZED

Yes

Yes, with the slack-byte algorithm

Yes, but eight-byte items are eight-byte aligned

TYPEDEF / TYPE

Yes (introduced in COBOL 2002)

Yes (6.5)

Accepted; no TYPE SECTION, no ::

TYPEDEF STRONG

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 REDEFINES sample carries a stray PICTURE keyword 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 is REDEFINES 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 TRUNC option and decimal scaling, which also decide what a REDEFINES of a binary item sees, as the example above shows.

  • RENAMES, SYNCHRONIZED and slack bytes are legacy layout tools that the book does not cover, and TYPEDEF/TYPE (Enterprise COBOL 6.5) and STRONG types (PTF PH73209) are newer than the book.

  • Examples written for 2022-era compilers show REDEFINES as the way to build every table or variant record. With TYPEDEF, reference modification and OCCURS (in Tables and OCCURS) it is only one of the tools.