Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

COBOL  Module 2 – Data definitions: PICTURE, levels, MOVE rules and edited output

PICTURE strings, literals and figurative constants

How a COBOL PICTURE string sets the bytes of an item, what S, V and P store, how literals fill a VALUE, and what each figurative constant puts in.

  • Beginner
  • 15 minutes
  • Examples run with GnuCOBOL 3.2 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 15 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Write PICTURE strings with 9, X, A, S, V and P and predict the bytes each item takes
  • Use numeric, alphanumeric and hexadecimal literals, and size each VALUE in bytes
  • Explain what SPACES, ZEROS, HIGH-VALUES, LOW-VALUES and ALL put into storage
  • Avoid data names that collide with the reserved words of a dialect

Before you start

What you’ll learn · Before you start

What you will learn

  • Write PICTURE strings with 9, X, A, S, V and P and predict the bytes each item takes
  • Use numeric, alphanumeric and hexadecimal literals, and size each VALUE in bytes
  • Explain what SPACES, ZEROS, HIGH-VALUES, LOW-VALUES and ALL put into storage
  • Avoid data names that collide with the reserved words of a dialect

Before you start

On this page

PIC S9(7)V99 holds a balance as large as 9,999,999.99, yet it takes 9 bytes, not 11: the sign and the decimal point get no byte of their own. Every COBOL data item is a fixed number of bytes set by its PICTURE string, and a record layout is right only when each field is counted the way the compiler counts it.

Below you will count the bytes of items built from 9, X, A, S, V and P and read each byte the compiler stores, write numeric, alphanumeric and hexadecimal literals and catch a VALUE that does not fit, fill items with figurative constants, and keep data names clear of the words a compiler reserves.

A PICTURE string sets the bytes of an item

A PICTURE clause: The clause, PIC for short, that describes an elementary item with symbols such as 9, X, A, S and V. In USAGE DISPLAY each 9, X or A is one byte, so PIC X(8) is 8 bytes., PIC for short, describes an item with symbols. 9 is a digit, X is any character and A is a letter or a space, and a number in brackets repeats the symbol before it, so 9(4) means 9999. In USAGE DISPLAY, the usage an item has when it names no other, each of those symbols is one byte, so the PICTURE string is the size of the item. For four items, this program prints the size from the BYTE-LENGTH function and the bytes from HEX-OF, which writes every byte as two hexadecimal digits:

pictures.cob: four items of three kinds COB · pictures.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. PICTURES.
      * Four items of the three basic kinds, each with its size in
      * bytes and its bytes in hexadecimal.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  ACCT-NO      PIC X(8)   VALUE "AC000417".
       01  BRANCH       PIC 9(4)   VALUE 42.
       01  INITIALS     PIC A(3)   VALUE "RKS".
       01  CITY         PIC X(12)  VALUE "NAGPUR".
       01  CODE-IN      PIC X(3)   VALUE "R2D".
       PROCEDURE DIVISION.
           DISPLAY "ACCT-NO   " FUNCTION BYTE-LENGTH(ACCT-NO)
                   " bytes  " FUNCTION HEX-OF(ACCT-NO)
           DISPLAY "BRANCH    " FUNCTION BYTE-LENGTH(BRANCH)
                   " bytes  " FUNCTION HEX-OF(BRANCH)
           DISPLAY "INITIALS  " FUNCTION BYTE-LENGTH(INITIALS)
                   " bytes  " FUNCTION HEX-OF(INITIALS)
           DISPLAY "CITY      " FUNCTION BYTE-LENGTH(CITY)
                   " bytes " FUNCTION HEX-OF(CITY)
           MOVE CODE-IN TO INITIALS
           DISPLAY "INITIALS now holds [" INITIALS "]"
           IF INITIALS IS ALPHABETIC
               DISPLAY "  and it is alphabetic"
           ELSE
               DISPLAY "  and it is not alphabetic"
           END-IF
           STOP RUN.
Sizes and bytes of the four items Python · pictures_session.py
from session import files, run

# Four items of the three basic kinds: their sizes in bytes, their bytes in hexadecimal, and what the PICTURE of an
# alphabetic item does and does not check.
files("pictures.cob")
run("""
cobc -x pictures.cob && ./pictures
""")

Output

$ cobc -x pictures.cob && ./pictures
ACCT-NO   8 bytes  4143303030343137
BRANCH    4 bytes  30303432
INITIALS  3 bytes  524B53
CITY      12 bytes 4E4147505552202020202020
INITIALS now holds [R2D]
  and it is not alphabetic

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 pictures_session.py

Each size is the count of symbols: X(8) gave 8 bytes, 9(4) gave 4 and A(3) gave 3. The bytes show how DISPLAY data is kept, as characters. BRANCH holds the number 42 as the four characters 0042, X’30303432’, and CITY holds NAGPUR followed by six spaces, each X’20’, because a value shorter than its item is padded on the right. The table sums up the three symbols:

Symbol A position may hold In pictures.cob
9 a digit, 0 to 9 BRANCH, PIC 9(4): 4 bytes
X any character ACCT-NO, PIC X(8): 8 bytes
A a letter or a space INITIALS, PIC A(3): 3 bytes

The last two lines of the run show what a PICTURE does not do. MOVE CODE-IN TO INITIALS put R2D into an item whose PICTURE promises letters, and nothing objected: the PICTURE describes what the item should hold and checks nothing at run time. Only the class test IS ALPHABETIC noticed the digit.

Test data from outside before you use it

A record read from a file or a screen can hold anything. Test it with IS NUMERIC or IS ALPHABETIC, as pictures.cob tests INITIALS, before a program calculates with it or stores it.

S, V and P add no bytes, unless the sign is separate

The amount 42.50 can be described in several ways, and only a separate sign costs an extra byte. V is the implied decimal point: The V of a PICTURE string. It tells the compiler where the decimal point falls for arithmetic and MOVE, but takes no byte, so PIC 9(3)V99 is 5 bytes.: it tells the compiler where the point falls, for arithmetic and for MOVE, and IBM’s reference says it is “not counted in the size of the elementary item”. S says the item has a sign and is not counted either, unless a SIGN clause makes the sign SEPARATE, which gives it a byte of its own. P is a scaling position: A P of a PICTURE string: a digit position that is never stored. PIC 9(3)PPP stores three digits and stands for a multiple of 1,000, so 123456 is held as 123000., a digit that is never stored. The program prints the size, the bytes and the displayed value of each form:

signs.cob: one amount, with and without a sign COB · signs.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SIGNS.
      * The same amount with and without a sign, the sign kept in a
      * byte of its own, and P scaling. V and S take no byte here.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  AMT-PLAIN    PIC 9(3)V99  VALUE 42.50.
       01  AMT-SIGNED   PIC S9(3)V99 VALUE -42.50.
       01  AMT-LEAD     PIC S9(3)V99 SIGN LEADING SEPARATE
                        VALUE -42.50.
       01  AMT-TRAIL    PIC S9(3)V99 SIGN TRAILING SEPARATE
                        VALUE -42.50.
       01  BALANCE      PIC S9(7)V99 VALUE -1234.50.
       01  THOUSANDS    PIC 9(3)PPP.
       PROCEDURE DIVISION.
           DISPLAY "AMT-PLAIN   " FUNCTION BYTE-LENGTH(AMT-PLAIN)
                   "  " FUNCTION HEX-OF(AMT-PLAIN) "    " AMT-PLAIN
           DISPLAY "AMT-SIGNED  " FUNCTION BYTE-LENGTH(AMT-SIGNED)
                   "  " FUNCTION HEX-OF(AMT-SIGNED) "    " AMT-SIGNED
           DISPLAY "AMT-LEAD    " FUNCTION BYTE-LENGTH(AMT-LEAD)
                   "  " FUNCTION HEX-OF(AMT-LEAD) "  " AMT-LEAD
           DISPLAY "AMT-TRAIL   " FUNCTION BYTE-LENGTH(AMT-TRAIL)
                   "  " FUNCTION HEX-OF(AMT-TRAIL) "  " AMT-TRAIL
           DISPLAY "BALANCE     " FUNCTION BYTE-LENGTH(BALANCE)
                   "  " FUNCTION HEX-OF(BALANCE) " " BALANCE
           MOVE 123456 TO THOUSANDS
           DISPLAY "THOUSANDS   " FUNCTION BYTE-LENGTH(THOUSANDS)
                   "  " FUNCTION HEX-OF(THOUSANDS) "        " THOUSANDS
           STOP RUN.
Sizes, bytes and displayed values Python · signs_session.py
from session import files, run

# The bytes of one amount with and without a sign, with the sign in a byte of its own, and an item scaled with P.
files("signs.cob")
run("""
cobc -x signs.cob && ./signs
""")

Output

$ cobc -x signs.cob && ./signs
AMT-PLAIN   5  3034323530    042.50
AMT-SIGNED  5  3034323570    -042.50
AMT-LEAD    6  2D3034323530  -042.50
AMT-TRAIL   6  30343235302D  042.50-
BALANCE     9  303030313233343570 -0001234.50
THOUSANDS   3  313233        123000

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 signs_session.py

AMT-PLAIN, PIC 9(3)V99, is five bytes, the digits 04250 with no point among them. AMT-SIGNED has the same five bytes except the last: GnuCOBOL keeps the sign of a signed DISPLAY item in its last byte, so X’30’, the character 0, became X’70’.

The same sign on z/OS

Where the sign goes is the compiler’s choice. IBM’s programming guide writes the sign byte of a signed DISPLAY item as X’sd’, a sign half, C for positive and D for negative, and a digit half. So -42.50 in PIC S9(3)V99 ends in X’D0’ on z/OS, not in the X’70’ that GnuCOBOL stored here.

SIGN LEADING SEPARATE and SIGN TRAILING SEPARATE add a sixth byte, a minus sign, X’2D’, in front of the digits or after them. Step through the bytes of AMT-LEAD:

Interactive · stage by stage The six bytes of -42.50 with a separate leading sign Step down the column. Each stage is one byte of AMT-LEAD, with the character and the hexadecimal value it holds.
The six bytes of -42.50 with a separate leading sign, step 5 of 5. Showing Byte 1: the sign, Byte 2: hundreds, Byte 3: tens, Byte 4: units, Byte 5: tenths, Byte 6: hundredths.Byte 1: the sign- is X'2D'Byte 2: hundreds0 is X'30'Byte 3: tens4 is X'34'Byte 4: units2 is X'32'Byte 5: tenths5 is X'35'Byte 6: hundredths0 is X'30'

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. A byte for the sign. SIGN LEADING SEPARATE gives the sign a byte of its own, in front of the digits. The value is negative, so the byte holds a minus sign, X'2D'.
  2. Three digits before the point. S9(3) gives three digit positions, one byte each. In USAGE DISPLAY a digit is stored as its character, so 42 becomes 0, 4 and 2, X'30', X'34' and X'32'.
  3. V takes no byte. V comes next in the PICTURE string, but nothing is stored for it. It only tells the compiler that the two digits after it are decimals.
  4. Two decimal digits. V99 gives two more digit positions, the tenths and the hundredths, which hold 5 and 0.
  5. Six bytes in all. The item is 6 bytes, 2D3034323530 in hexadecimal, as HEX-OF printed it. AMT-SIGNED holds the same value in 5 bytes, because without SEPARATE the sign goes into the last byte, which becomes X'70'.

BALANCE is the field of the opening: nine digits, 9 bytes, 303030313233343570. THOUSANDS, PIC 9(3)PPP, is 3 bytes that hold 123 and stand for 123000. The three Ps are the units, tens and hundreds it never stores, so MOVE 123456 TO THOUSANDS kept the thousands and dropped 456 without a word.

Key idea

Count the 9s, Xs and As to size an item in USAGE DISPLAY: S, V and P add no byte, and SIGN … SEPARATE adds exactly one, for the sign.

Checkpoint

Check: Bytes from 9, X and A · S, V and P, and a separate sign

  1. Question 1 of 2 BRANCH is PIC 9(4) VALUE 42 in USAGE DISPLAY. Which bytes does it hold?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: X'30303432', the characters 0042

    PIC 9(4) is four bytes in USAGE DISPLAY, and a number is kept as its digit characters, aligned to the right: the session printed 30303432 for BRANCH.

  2. Question 2 of 2 How many bytes does PIC S9(5)V99 SIGN TRAILING SEPARATE take in USAGE DISPLAY?

    Type a number.

    A hint

    Count the digit positions first, then ask which symbol gets a byte because of SEPARATE.

    Show the answer: Question 2 of 2

    Answer: 8 bytes

    S9(5)V99 has seven digit positions, one byte each. V adds nothing, and the sign, which would otherwise share the last byte, gets a byte of its own because it is SEPARATE: 7 + 1 = 8, as AMT-TRAIL of signs.cob took 5 + 1 = 6.

Literals are bytes, and a VALUE must fit them

A literal is a value written into the program. A numeric literal is digits with at most one sign, at the left, and at most one decimal point, as in -2500.75. An alphanumeric literal stands between quotation marks or apostrophes, and the delimiter itself is written twice inside it, as in ‘Payee’‘s copy’. A hexadecimal literal: A literal written X'…' with two hexadecimal digits for each byte, such as X'414243' for ABC or X'09' for a tab. It gives exact bytes, printable or not., X’…‘, gives the bytes themselves, two hexadecimal digits for each, and IBM allows one anywhere an alphanumeric literal may stand: X’414243’ is ABC, and X’09’ is a tab, which no keyboard puts between quotes. A VALUE clause gives an item its starting value from a literal. Here are four literals that fit their items and three that do not:

literals.cob: VALUE clauses, three of them too long COB · literals.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. LITERALS.
      * Literals in VALUE clauses: four that fit, three that do not.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  NOTE-TEXT    PIC X(12)    VALUE 'Payee''s copy'.
       01  LETTERS      PIC X(3)     VALUE X'414243'.
       01  TAB-CHAR     PIC X        VALUE X'09'.
       01  OVERDRAFT    PIC S9(5)V99 VALUE -2500.75.
       01  STATION      PIC X(10)    VALUE "CHENNAI CENTRAL".
       01  LIMIT-AMT    PIC 9(3)     VALUE 12345.
       01  PAYEE        PIC X(20)
                        VALUE "नमिता पाल".
       PROCEDURE DIVISION.
           DISPLAY "NOTE-TEXT [" NOTE-TEXT "]"
           DISPLAY "LETTERS   [" LETTERS "]"
           DISPLAY "TAB-CHAR  [" FUNCTION HEX-OF(TAB-CHAR) "]"
           DISPLAY "OVERDRAFT [" OVERDRAFT "]"
           DISPLAY "STATION   [" STATION "]"
           DISPLAY "LIMIT-AMT [" LIMIT-AMT "]"
           DISPLAY "PAYEE     [" PAYEE "]"
           STOP RUN.

The session keeps only cobc’s own messages, the lines that start with the file name, then runs the program and builds it once more with the warning turned into an error:

What cobc says, and what the program holds Python · literals_session.py
from session import files, run

# Literals in VALUE clauses: what cobc says about three that do not fit (only its own messages, the lines that start
# with the file name), what the program then holds, and the same build with that warning made an error.
files("literals.cob")
run("""
cobc -x literals.cob 2>&1 | grep '^literals.cob'
./literals
!cobc -x -Werror=others -o literals-strict literals.cob
""")

Output

$ cobc -x literals.cob 2>&1 | grep '^literals.cob'
literals.cob:10: warning: value size exceeds data size [-Wothers]
literals.cob:10: note: value size is 15 [-Wothers]
literals.cob:11: warning: value size exceeds data size [-Wothers]
literals.cob:13: warning: value size exceeds data size [-Wothers]
literals.cob:13: note: value size is 25 [-Wothers]
$ ./literals
NOTE-TEXT [Payee's copy]
LETTERS   [ABC]
TAB-CHAR  [09]
OVERDRAFT [-02500.75]
STATION   [CHENNAI CE]
LIMIT-AMT [345]
PAYEE     [नमिता प�]
$ cobc -x -Werror=others -o literals-strict literals.cob
literals.cob:10: error: value size exceeds data size [-Werror=others]
    8 |        01  TAB-CHAR     PIC X        VALUE X'09'.
    9 |        01  OVERDRAFT    PIC S9(5)V99 VALUE -2500.75.
   10 >        01  STATION      PIC X(10)    VALUE "CHENNAI CENTRAL".
   11 |        01  LIMIT-AMT    PIC 9(3)     VALUE 12345.
   12 |        01  PAYEE        PIC X(20)
literals.cob:10: note: value size is 15 [-Werror=others]
literals.cob:11: error: value size exceeds data size [-Werror=others]
    9 |        01  OVERDRAFT    PIC S9(5)V99 VALUE -2500.75.
   10 |        01  STATION      PIC X(10)    VALUE "CHENNAI CENTRAL".
   11 >        01  LIMIT-AMT    PIC 9(3)     VALUE 12345.
   12 |        01  PAYEE        PIC X(20)
   13 |                         VALUE "नमिता पाल".
literals.cob:13: error: value size exceeds data size [-Werror=others]
   11 |        01  LIMIT-AMT    PIC 9(3)     VALUE 12345.
   12 |        01  PAYEE        PIC X(20)
   13 >                         VALUE "नमिता पाल".
   14 |        PROCEDURE DIVISION.
   15 |            DISPLAY "NOTE-TEXT [" NOTE-TEXT "]"
literals.cob:13: note: value size is 25 [-Werror=others]
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 literals_session.py

The four that fit hold what was written: Payee’s copy with one apostrophe, ABC, the tab byte 09, and -2500.75, which DISPLAY showed as -02500.75. For the other three, GnuCOBOL warned three times, value size exceeds data size, and built the program anyway. The alphanumeric STATION kept its first 10 bytes, CHENNAI CE, and the numeric LIMIT-AMT kept its last three digits, 345 of 12345: the rules of MOVE, which the next lesson takes apart. PAYEE shows that sizes are counted in bytes, not letters. The name नमिता पाल is 9 Unicode characters, a space and eight Devanagari ones, and in UTF-8 each Devanagari character takes 3 bytes, so the literal is 25 bytes. cobc reported value size is 25 and kept 20 bytes, which end one byte into the vowel sign after प: the terminal shows that broken character as �, and ल is lost.

Item and PICTURE VALUE What it held
STATION, X(10) CHENNAI CENTRAL, 15 bytes CHENNAI CE
LIMIT-AMT, 9(3) 12345 345
PAYEE, X(20) 9 characters, 25 bytes its first 20 bytes

Letting a value-size warning pass

Wrong: shipping a build whose log says value size exceeds data size, as if the item would grow to fit. Right: size each item in bytes for its longest value, PIC X(25) for the name, and build with -Werror=others, so that a VALUE that does not fit stops the build, as the last command showed.

Figurative constants fill every byte

A figurative constant: A reserved word that stands for a value, such as SPACES, ZEROS, HIGH-VALUES, LOW-VALUES, QUOTES or ALL with a literal. It takes the length of the item it fills. is a reserved word that stands for a value. The ones this lesson uses are SPACE or SPACES, ZERO, ZEROS or ZEROES, HIGH-VALUE or HIGH-VALUES, LOW-VALUE or LOW-VALUES, QUOTE or QUOTES, and ALL followed by a literal. It has no length of its own. IBM’s reference gives it the length of the item it is moved to, so it repeats until every byte is filled. This program moves each one into an item and prints the bytes, then tries to clear a number with SPACES:

figurative.cob: each constant moved into an item COB · figurative.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. FIGURATIVE.
      * What each figurative constant puts into an item: every byte
      * of the item is filled.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  FOUR         PIC X(4).
       01  QTY-4        PIC 9(4).
       01  RULE-LINE    PIC X(10).
       01  CODE-5       PIC X(5).
       PROCEDURE DIVISION.
           MOVE SPACES TO FOUR
           DISPLAY "SPACES          " FUNCTION HEX-OF(FOUR)
           MOVE ZEROS TO FOUR
           DISPLAY "ZEROS           " FUNCTION HEX-OF(FOUR)
           MOVE ZEROS TO QTY-4
           DISPLAY "ZEROS into 9(4) " FUNCTION HEX-OF(QTY-4)
           MOVE HIGH-VALUES TO FOUR
           DISPLAY "HIGH-VALUES     " FUNCTION HEX-OF(FOUR)
           MOVE LOW-VALUES TO FOUR
           DISPLAY "LOW-VALUES      " FUNCTION HEX-OF(FOUR)
           MOVE QUOTES TO FOUR
           DISPLAY "QUOTES          " FUNCTION HEX-OF(FOUR)
                   "  " FOUR
           MOVE ALL "*-" TO RULE-LINE
           DISPLAY "ALL '*-'        " RULE-LINE
           MOVE ALL "AB" TO CODE-5
           DISPLAY "ALL 'AB'        " CODE-5
           STOP RUN.
The bytes of each constant, and SPACES into a number Python · figurative_session.py
from session import files, run

# The bytes each figurative constant puts into an item, and SPACES moved to a numeric item.
files("figurative.cob", "spaces-num.cob")
run("""
cobc -x figurative.cob && ./figurative
!cobc -x spaces-num.cob
""")

Output

$ cobc -x figurative.cob && ./figurative
SPACES          20202020
ZEROS           30303030
ZEROS into 9(4) 30303030
HIGH-VALUES     FFFFFFFF
LOW-VALUES      00000000
QUOTES          22222222  """"
ALL '*-'        *-*-*-*-*-
ALL 'AB'        ABABA
$ cobc -x spaces-num.cob
spaces-num.cob:8: error: MOVE of figurative constant SPACE to numeric item used
    6 |        01  QTY-4        PIC 9(4).
    7 |        PROCEDURE DIVISION.
    8 >            MOVE SPACES TO QTY-4
    9 |            DISPLAY QTY-4
   10 |            STOP RUN.
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 figurative_session.py

Constant Each byte holds In figurative.cob
SPACES a space 20202020
ZEROS the character 0 30303030, in PIC X(4) and in PIC 9(4)
HIGH-VALUES the highest character of the collating sequence FFFFFFFF
LOW-VALUES the lowest character of the collating sequence 00000000
QUOTES a quotation mark 22222222
ALL "*-" the literal, repeated *-*-*-*-*- in PIC X(10)

HIGH-VALUES and LOW-VALUES are bytes no keyboard types. IBM’s reference defines them by the collating sequence: The order in which a program or a sort ranks characters when it compares them. ASCII puts digits before letters and EBCDIC puts letters before digits; COLLATING SEQUENCE names the one a SORT or MERGE uses. More in “SORT and MERGE: input and output procedures”: the character with the highest or the lowest position in it, X’FF’ and X’00’ in EBCDIC, and the same bytes in GnuCOBOL’s native order here. Because no real key can be higher, programs move HIGH-VALUES into a key to mean “no more records”, a pattern the lessons on batch files build on. ALL “AB” in five bytes gave ABABA: the pattern repeats and stops where the item ends, half-way through it.

The last command shows a constant that is refused. MOVE SPACES TO QTY-4 failed to compile, MOVE of figurative constant SPACE to numeric item used, because spaces are not digits. ZEROS is the constant that clears a number, and it stores the same bytes in a numeric item as in an alphanumeric one.

Key idea

A figurative constant takes the length of the item it fills: MOVE SPACES clears every byte, and MOVE ALL "*-" repeats the pattern to the last one.

Checkpoint

Check: Literals and VALUE sizes · What figurative constants store

  1. Question 1 of 2 STATION is PIC X(10) VALUE "CHENNAI CENTRAL". What happened when literals.cob was built and run with GnuCOBOL?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: cobc warned and the program held CHENNAI CE

    A VALUE that does not fit is cut as a MOVE would cut it. GnuCOBOL warned three times and built the program, which printed STATION [CHENNAI CE].

  2. Question 2 of 2 CODE-5 is PIC X(5). What does it hold after MOVE ALL "AB" TO CODE-5?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: ABABA

    A figurative constant takes the length of the item it fills, so ALL "AB" in five bytes is ABABA, and ALL "-" in ten bytes was -----.

A data name must not be a reserved word

The words of the language itself, such as MOVE, COUNT or STATUS, are reserved word: A word the COBOL language itself uses, such as COUNT or STATUS, which cannot name a data item or a paragraph. cobc --list-reserved lists the reserved words of GnuCOBOL. More in “Install GnuCOBOL, compile with cobc and run programs”, and no data item may be named with one. The trouble is that each compiler, and each dialect of a compiler, has its own list. This loan program names its monthly instalment EMI:

loan.cob: an item named EMI COB · loan.cob
       IDENTIFICATION DIVISION.
       PROGRAM-ID. LOAN.
      * A loan program that names its monthly instalment EMI.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  EMI          PIC 9(6)V99 VALUE 8678.23.
       01  TENURE       PIC 9(3)    VALUE 240.
       PROCEDURE DIVISION.
           DISPLAY "Instalment " EMI " for " TENURE " months"
           STOP RUN.
EMI, the reserved words of two dialects, and a prefix Python · reserved_session.py
from session import files, run

# A data name that is a reserved word, the reserved-word lists of two dialects, and the fix: a prefix on every name.
files("loan.cob", "loan-fixed.cob")
run("""
!cobc -x loan.cob
cobc --list-reserved | grep -E '^(BYTES|CD|EMI|ESI) '
cobc -std=cobol2014 --list-reserved | grep -E '^(BYTES|CD|EMI|ESI) ' || echo "none of the four"
cobc -x loan-fixed.cob && ./loan-fixed
""")

Output

$ cobc -x loan.cob
loan.cob:6: error: syntax error, unexpected EMI
    4 |        DATA DIVISION.
    5 |        WORKING-STORAGE SECTION.
    6 >        01  EMI          PIC 9(6)V99 VALUE 8678.23.
    7 |        01  TENURE       PIC 9(3)    VALUE 240.
    8 |        PROCEDURE DIVISION.
loan.cob:9: error: syntax error, unexpected EMI
    7 |        01  TENURE       PIC 9(3)    VALUE 240.
    8 |        PROCEDURE DIVISION.
    9 >            DISPLAY "Instalment " EMI " for " TENURE " months"
   10 |            STOP RUN.
   11 | <EOF>
[exit status 1]
$ cobc --list-reserved | grep -E '^(BYTES|CD|EMI|ESI) '
BYTES                           No
CD                              Yes
EMI                             Yes
ESI                             Yes
$ cobc -std=cobol2014 --list-reserved | grep -E '^(BYTES|CD|EMI|ESI) ' || echo "none of the four"
none of the four
$ cobc -x loan-fixed.cob && ./loan-fixed
Instalment 008678.23 for 240 months

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 reserved_session.py

cobc stopped with syntax error, unexpected EMI, a message that never says the word is reserved. The list explains it: in GnuCOBOL’s default dialect EMI, CD and ESI are reserved words, and BYTES is reserved but not supported. Under -std=cobol2014 none of the four is reserved, and that does not make EMI safe. IBM’s table for Enterprise COBOL marks EMI, CD and ESI as words of the 1985 standard that it reserves without implementing, and naming an item with one of them gives a severe message; BYTES is not in IBM’s table at all. A name can build under one dialect and fail under another. Whether each word is reserved:

Word GnuCOBOL GnuCOBOL, cobol2014 IBM 6.5
EMI yes no yes, standard only
CD yes no yes, standard only
BYTES yes, not supported no no
COUNT yes yes yes

The fix is a habit rather than a list: give every data name a prefix, such as LN- for the items of a loan or WS- for working storage. No reserved word starts with one, so loan-fixed.cob, with LN-EMI and LN-TENURE, built and printed its instalment. GnuCOBOL’s -fnot-reserved=EMI would also take the word off the list, but only for GnuCOBOL: the same source would still fail on z/OS.

EMI in Indian loan programs

EMI, short for equated monthly instalment, is the usual name for the monthly payment of a loan in India. It is therefore a natural data name in a loan program written there, and one that GnuCOBOL’s default dialect and IBM’s compiler both refuse.

Checkpoint

Check: Data names and reserved words

  1. One question A program must build with GnuCOBOL -std=cobol2014 and with IBM Enterprise COBOL. Can a data item be named EMI?

    Choose one answer.

    Show the answer: One question

    Answer: No, rename it with a prefix such as LN-EMI

    A name has to be clear of the reserved words of every compiler that builds the program. A prefix such as LN- or WS- keeps every name clear without knowing every list.

Practise: count the bytes, read the constants

Count the bytes and read the constants until the sizes come without counting on your fingers. The questions start with the idea you know least, and a wrong choice says which byte it miscounted:

Practice that adapts to you

Practise this lesson

17 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 17 How many bytes does an item of PIC X(12) take in USAGE DISPLAY?

    Type a number.

    Show the answer: Question 1 of 17

    Answer: 12 bytes

    Each X is one byte and (12) repeats it twelve times. CITY in pictures.cob is PIC X(12), and BYTE-LENGTH printed 12.

  2. Question 2 of 17 CITY is PIC X(12) VALUE "NAGPUR". What are its last six bytes?

    Choose one answer.

    Show the answer: Question 2 of 17

    Answer: Six spaces, each X'20'

    NAGPUR fills six of the twelve bytes; the other six are spaces, so CITY printed as 4E4147505552 followed by six 20s.

  3. Question 3 of 17 A record from another system puts R2D into INITIALS, PIC A(3), through a MOVE. What happens?

    Choose one answer.

    Show the answer: Question 3 of 17

    Answer: The MOVE stores R2D, and only a test such as IS ALPHABETIC finds the digit

    Data from outside can break any PICTURE. Test it with IS ALPHABETIC or IS NUMERIC before you rely on it: the session printed INITIALS now holds [R2D] and it is not alphabetic.

  4. Question 4 of 17 What does the V of PIC 9(3)V99 store?

    Choose one answer.

    Show the answer: Question 4 of 17

    Answer: Nothing; it only marks where the decimal point falls

    An implied decimal point is a fact about the item that the compiler uses for alignment and arithmetic; the data itself is only digits.

  5. Question 5 of 17 How many bytes does BALANCE, PIC S9(7)V99, take in USAGE DISPLAY?

    Type a number.

    Show the answer: Question 5 of 17

    Answer: 9 bytes

    Nine digit positions, one byte each; S and V add nothing. The session printed 9 for BALANCE, the field of the opening.

  6. Question 6 of 17 THOUSANDS is PIC 9(3)PPP. What does DISPLAY THOUSANDS print after MOVE 987654 TO THOUSANDS?

    Choose one answer.

    Show the answer: Question 6 of 17

    Answer: 987000

    P is a digit position that is never stored. With PPP at the right, the item holds a number of thousands, so 987654 becomes 987000, as 123456 became 123000.

  7. Question 7 of 17 AMT-SIGNED, PIC S9(3)V99, holds -42.50. In which byte would z/OS keep the sign, and as what?

    Choose one answer.

    Show the answer: Question 7 of 17

    Answer: In the last byte, which becomes X'D0'

    Without SEPARATE the sign shares the last byte with the last digit. The bytes differ by compiler, X'70' here and X'D0' on z/OS, which is why data moved between them is converted with care.

  8. Question 8 of 17 What does VALUE X'414243' put into an item of PIC X(3)?

    Choose one answer.

    Show the answer: Question 8 of 17

    Answer: The bytes 41, 42 and 43, which are ABC

    X'…' writes the bytes themselves, which is how a program puts a tab, X'09', or any byte that has no key into an item.

  9. Question 9 of 17 Which literal, between apostrophes, holds the text Payee's copy?

    Choose one answer.

    Show the answer: Question 9 of 17

    Answer: 'Payee''s copy'

    Inside an alphanumeric literal, two delimiters in a row stand for one. Quotation marks work the same way inside a literal between quotation marks.

  10. Question 10 of 17 An item is PIC 9(4) VALUE 123456. GnuCOBOL builds it with a warning. What does the item hold?

    Choose one answer.

    Show the answer: Question 10 of 17

    Answer: 3456

    A number is aligned on its units digit, so the digits that do not fit fall off the left: 123456 in four digits is 3456.

  11. Question 11 of 17 A name has 6 Devanagari characters and no spaces. How many bytes must its PIC X item have to hold it in UTF-8?

    Type a number.

    A hint

    Each Devanagari character of the lesson took 3 bytes in UTF-8.

    Show the answer: Question 11 of 17

    Answer: 18 bytes

    Sizes are bytes, not letters: 6 characters of 3 bytes each are 18 bytes, so PIC X(18). The 9 characters of the lesson's name, one of them a space, were 25 bytes.

  12. Question 12 of 17 Which bytes did MOVE HIGH-VALUES put into the 4-byte item of figurative.cob?

    Choose one answer.

    Show the answer: Question 12 of 17

    Answer: FFFFFFFF

    HIGH-VALUES and LOW-VALUES are the highest and lowest characters of the collating sequence, X'FF' and X'00' in the session, which is why a key of HIGH-VALUES sorts after every real key.

  13. Question 13 of 17 QTY-4 is PIC 9(4). Which statement clears it?

    Choose one answer.

    Show the answer: Question 13 of 17

    Answer: MOVE ZEROS TO QTY-4

    Clear numbers with ZEROS and alphanumeric items with SPACES. GnuCOBOL refuses SPACES into a numeric item at compile time.

  14. Question 14 of 17 What does MOVE ALL "*-" TO an item of PIC X(7) store?

    Choose one answer.

    Show the answer: Question 14 of 17

    Answer: ---

    A figurative constant takes the length of the item, so seven bytes take three and a half copies of *-.

  15. Question 15 of 17 What did cobc report for loan.cob, which names an item EMI?

    Choose one answer.

    Show the answer: Question 15 of 17

    Answer: syntax error, unexpected EMI

    A reserved word used as a data name often shows up as a syntax error that names the word, which is the clue to check cobc --list-reserved.

  16. Question 16 of 17 Which data name is safe from the reserved words of GnuCOBOL and IBM Enterprise COBOL alike?

    Choose one answer.

    Show the answer: Question 16 of 17

    Answer: WS-COUNT

    A prefix is the habit that works without knowing every list: WS-COUNT, LN-EMI and WS-BYTES are all clear.

  17. Question 17 of 17 A program with an item named BYTES builds on z/OS. What will GnuCOBOL's default dialect do with it?

    Choose one answer.

    Show the answer: Question 17 of 17

    Answer: Refuse it, because BYTES is reserved there although IBM does not reserve it

    Moving code between compilers means checking names against the new compiler's list, or, better, having prefixed names that no list contains.

Predict a size before you run it

Add 01 AMT-NEW PIC S9(5)V99 SIGN TRAILING SEPARATE to signs.cob, with VALUE -1250.75. on the next line as AMT-TRAIL has it, and a DISPLAY of its BYTE-LENGTH and HEX-OF. Write down your prediction, then build it with cobc -x signs.cob && ./signs: 8 bytes, 303132353037352D, seven digits and the minus sign after them.

Interview questions

Warm-up (fresher to 2–5 years): how many bytes does PIC S9(5)V99 take in USAGE DISPLAY, and why?

Seven. In USAGE DISPLAY each 9 is one byte, a digit kept as a character, and S9(5)V99 has seven of them. The S only says that the item is signed: by default the sign shares the last byte with the last digit, so it costs nothing, and IBM’s reference says S is not counted in the size. The V marks where the decimal point falls and is not stored either, so 123.45 is kept as the digits 0012345. Two things change the count. SIGN LEADING SEPARATE or SIGN TRAILING SEPARATE gives the sign a byte of its own, which makes eight, and another USAGE, such as packed decimal, packs the digits into fewer bytes. FUNCTION BYTE-LENGTH reports the size, so a test can check it instead of a reader counting by eye.

Two harder questions apply these ideas: a record whose fields moved, and a build full of value-size warnings. Try your own answer before you open the first step of each:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    A colleague adds BALANCE PIC S9(7)V99 to a 120-byte record and, counting a byte for the sign and one for the point, shortens the last FILLER by 11 bytes. The reading system, given the same layout, now finds every field after BALANCE in the wrong place. Why, and how do you check the layout?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    A legacy GnuCOBOL build prints 240 warnings of value size exceeds data size, and the team wants to build with -Werror=others. Which of these warnings can change what a program does, how do you sort them, and how do you switch the flag on without stopping every build?

    Model answer, Pro. First step and follow-ups

Organisations named on this page

MySmartCoPilot is not connected with IBM or the GnuCOBOL project. The PICTURE, SIGN and literal rules quoted here come from their manuals, listed under References; the bytes and the messages come from runs of GnuCOBOL 3.2.

Flashcards · 8 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. How many bytes does PIC S9(7)V99 take in USAGE DISPLAY?

    9. Every 9 is a byte; S and V cost nothing, since the sign lives in the last digit's byte and the point is only implied.

  2. What may a position of PICTURE 9, X and A hold?

    9 holds a digit, X any character, A a letter or a space. A number in brackets repeats a symbol, so 9(4) means 9999.

  3. Can a digit be moved into an item of PIC A?

    Yes. A PICTURE describes what an item should hold and checks nothing at run time; only a class test such as IS ALPHABETIC notices the digit.

  4. What does SIGN LEADING SEPARATE add to an item?

    One byte, holding the sign as a character of its own in front of the digits; TRAILING SEPARATE puts it after them. Without SEPARATE the sign costs no byte.

  5. PIC 9(3)PPP receives MOVE 123456. What does it keep?

    123, meaning 123000. The Ps stand for digit positions that are never stored, so 456 is dropped without a warning.

  6. What does GnuCOBOL do with a VALUE too long for its item?

    It warns "value size exceeds data size", builds anyway and keeps part of the value: CHENNAI CE of CHENNAI CENTRAL, 345 of 12345. -Werror=others turns the warning into a failed build.

  7. How long is a figurative constant such as SPACES or ALL "*-"?

    It has no length of its own: it takes the length of the item it fills and repeats until the last byte. ALL "AB" in five bytes gives ABABA.

  8. Why may a data item named EMI fail to compile?

    EMI is reserved in GnuCOBOL's default dialect, and IBM's compiler reserves it too, although -std=cobol2014 does not. A prefix on every data name, such as LN-EMI, avoids every dialect's list.

Key takeaways

  • In USAGE DISPLAY each 9, X or A of a PICTURE string is one byte, so PIC X(8) is 8 bytes and PIC 9(4) holds 42 as the four characters 0042.
  • S and V take no byte, so PIC S9(7)V99 is 9 bytes; SIGN … SEPARATE adds one byte for the sign, and P scales a value by digits that are never stored.
  • Sizes are counted in bytes: GnuCOBOL only warns when a VALUE does not fit and keeps part of it, CHENNAI CE or 345, so a build with -Werror=others is the safer one.
  • A figurative constant takes the length of the item it fills: SPACES puts X’20’ in every byte, HIGH-VALUES X’FF’, LOW-VALUES X’00’, and ALL repeats its literal to the end.
  • Reserved words differ by compiler and dialect, as EMI showed, so a prefix on every data name keeps a program buildable everywhere.

Terms in this lesson

figurative constant
A reserved word that stands for a value, such as SPACES, ZEROS, HIGH-VALUES, LOW-VALUES, QUOTES or ALL with a literal. It takes the length of the item it fills.
hexadecimal literal
A literal written X'…' with two hexadecimal digits for each byte, such as X'414243' for ABC or X'09' for a tab. It gives exact bytes, printable or not.
implied decimal point
The V of a PICTURE string. It tells the compiler where the decimal point falls for arithmetic and MOVE, but takes no byte, so PIC 9(3)V99 is 5 bytes.
PICTURE clause
The clause, PIC for short, that describes an elementary item with symbols such as 9, X, A, S and V. In USAGE DISPLAY each 9, X or A is one byte, so PIC X(8) is 8 bytes.
scaling position
A P of a PICTURE string: a digit position that is never stored. PIC 9(3)PPP stores three digits and stands for a multiple of 1,000, so 123456 is held as 123000.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.