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.
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:
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. 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:
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. 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:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- 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'.
- 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'.
- 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.
- Two decimal digits. V99 gives two more digit positions, the tenths and the hundredths, which hold 5 and 0.
- 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
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:
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:
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:
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. 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
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:
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. 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
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.
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.
-
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?
-
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?
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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
- Enterprise COBOL for z/OS 6.5: PICTURE clause (IBM)
- Enterprise COBOL for z/OS 6.5: Symbols used in the PICTURE clause (IBM)
- Enterprise COBOL for z/OS 6.5: SIGN clause (IBM)
- Enterprise COBOL for z/OS 6.5: Sign representation of zoned and packed-decimal data (IBM)
- Enterprise COBOL for z/OS 6.5: Numeric literals (IBM)
- Enterprise COBOL for z/OS 6.5: Hexadecimal notation for alphanumeric literals (IBM)
- Enterprise COBOL for z/OS 6.5: Figurative constants (IBM)
- Enterprise COBOL for z/OS 6.5: BYTE-LENGTH (IBM)
- Enterprise COBOL for z/OS 6.5: HEX-OF (IBM)
- Enterprise COBOL for z/OS 6.5: Reserved words (IBM)
- RFC 3629: UTF-8, a transformation format of ISO 10646 (IETF)
- GnuCOBOL 3.2 NEWS (GnuCOBOL project (GNU))
- GnuCOBOL manual: compiler options (GnuCOBOL project (GNU))
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress