Beginner

Variables and Types in COBOL

Learn how COBOL defines variables with PIC clauses, level numbers, and WORKING-STORAGE — the unique data model behind the language that runs the world

COBOL’s approach to variables is unlike any modern language. Rather than declaring int x = 5 or name: str, COBOL uses PIC clauses (PICTURE clauses) that describe the physical format of each data item — specifying exactly how many digits, characters, or decimal places a variable can hold. This reflects COBOL’s business-data origins: a variable isn’t just a type, it’s a layout specification.

All variables in a COBOL program are defined in the DATA DIVISION, specifically in the WORKING-STORAGE SECTION. There are no variable declarations scattered through procedure code — every variable is declared upfront, organized in a hierarchical structure using level numbers. This keeps data definitions centralized and makes programs easier to audit, a critical property for financial systems.

COBOL’s type system is statically typed and strong. The compiler knows the format of every variable at compile time, and conversions between numeric and text types must be done explicitly. This strictness has proven valuable over decades of business computing — implicit type coercions that silently corrupt financial data are not an option.

In this tutorial you’ll learn how to declare numeric variables, alphanumeric strings, and structured records, and how COBOL’s level-number hierarchy creates data structures without a separate struct keyword.


PIC Clauses and Level Numbers

Every COBOL variable declaration has this form:

level-number data-name PIC picture-string [VALUE initial-value].

The level number determines the variable’s place in a hierarchy:

  • 01 — Top-level group or elementary item
  • 0249 — Subordinate items nested inside a group
  • 77 — Standalone elementary item (no group membership)
  • 88 — Condition name (a named boolean test on a parent item)

The PIC string describes the data format using symbols:

SymbolMeaning
XAny alphanumeric character
9Numeric digit (0–9)
AAlphabetic character
VImplied decimal point (no stored character)
SSign (+ or −)

Repetitions are written as X(10) (ten characters) or 9(5) (five digits).


Example 1: Basic Variable Declarations

Create a file named variable.cob:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
IDENTIFICATION DIVISION.
PROGRAM-ID. VARIABLES.

DATA DIVISION.
WORKING-STORAGE SECTION.
*> Alphanumeric string  20 characters wide
01 WS-NAME            PIC X(20)  VALUE "Alice".

*> Integer  3 digits, no decimal
01 WS-AGE             PIC 9(3)   VALUE 30.

*> Fixed-point  5 digits, implied 2 decimal places (e.g., 123.45)
01 WS-SALARY          PIC 9(7)V99 VALUE 52000.00.

*> Signed integer  can hold negative values
01 WS-TEMPERATURE     PIC S9(3)  VALUE -15.

*> Boolean-style flag (Y or N)
01 WS-ACTIVE-FLAG     PIC X(1)   VALUE "Y".

PROCEDURE DIVISION.
    DISPLAY "Name:        " WS-NAME.
    DISPLAY "Age:         " WS-AGE.
    DISPLAY "Salary:      " WS-SALARY.
    DISPLAY "Temperature: " WS-TEMPERATURE.
    DISPLAY "Active:      " WS-ACTIVE-FLAG.
    STOP RUN.

Running with Docker

1
2
3
docker pull esolang/cobol:latest

docker run --rm -v $(pwd):/app -w /app esolang/cobol sh -c 'cobc -x -free variable.cob && ./variable'

Expected Output

Name:        Alice
Age:         030
Salary:      005200000
Temperature: -015
Active:      Y

Note on COBOL numeric display: WS-SALARY is stored as 9(7)V99 — seven integer digits plus two implied decimal places, giving nine raw digit positions total. When displayed with DISPLAY, GnuCOBOL prints all nine digits without the decimal point (since V is an implied point, not a stored character), so 52000.00 appears as 005200000. Use a separate edited (formatted) field with PIC ZZZ,ZZZ.99 to display with a real decimal point. Similarly, WS-AGE is three digits wide so it displays as 030, and WS-TEMPERATURE PIC S9(3) stores three digit positions plus a sign, displaying as -015.


Example 2: Group Items and Nested Level Numbers

COBOL builds record structures using level-number hierarchies. A level-01 item with nested levels becomes a group item — COBOL’s equivalent of a struct.

Create a file named variables-group.cob:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
IDENTIFICATION DIVISION.
PROGRAM-ID. VARIABLES-GROUP.

DATA DIVISION.
WORKING-STORAGE SECTION.

*> A date record broken into components
01 WS-DATE.
   05 WS-YEAR         PIC 9(4).
   05 WS-MONTH        PIC 9(2).
   05 WS-DAY          PIC 9(2).

*> An employee record
01 WS-EMPLOYEE.
   05 WS-EMP-ID       PIC 9(6).
   05 WS-EMP-NAME.
      10 WS-FIRST-NAME PIC X(15).
      10 WS-LAST-NAME  PIC X(20).
   05 WS-EMP-DEPT     PIC X(10).

PROCEDURE DIVISION.
    MOVE 2026          TO WS-YEAR.
    MOVE 3             TO WS-MONTH.
    MOVE 11            TO WS-DAY.

    MOVE 100042        TO WS-EMP-ID.
    MOVE "Grace"       TO WS-FIRST-NAME.
    MOVE "Hopper"      TO WS-LAST-NAME.
    MOVE "Engineer"   TO WS-EMP-DEPT.

    DISPLAY "Date:       " WS-YEAR "-" WS-MONTH "-" WS-DAY.
    DISPLAY "Employee:   " WS-EMP-ID " "
                           WS-FIRST-NAME WS-LAST-NAME.
    DISPLAY "Department: " WS-EMP-DEPT.
    STOP RUN.

Running with Docker

1
2
3
docker pull esolang/cobol:latest

docker run --rm -v $(pwd):/app -w /app esolang/cobol sh -c 'cobc -x -free variables-group.cob && ./variables-group'

Expected Output

Date:       2026-03-11
Employee:   100042 Grace          Hopper
Department: Engineer

Group items as strings: A group item like WS-DATE can also be referenced as a whole — it behaves as an alphanumeric string formed by concatenating all subordinate fields. This is how COBOL handles structured I/O: you can read or write the entire record in one operation.


Example 3: Constants, Condition Names, and Type Conversions

COBOL provides two mechanisms for constants and a unique feature — condition names (88 level) — that create named boolean tests on a variable’s value.

Create a file named variables-const.cob:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
IDENTIFICATION DIVISION.
PROGRAM-ID. VARIABLES-CONST.

DATA DIVISION.
WORKING-STORAGE SECTION.

*> Named constant  77 level with VALUE, never changed by procedure
77 WS-PI              PIC 9V9(6)  VALUE 3.141593.
77 WS-COMPANY-NAME    PIC X(20)   VALUE "CodeArchaeology".
77 WS-MAX-RETRIES     PIC 9(2)    VALUE 5.

*> Condition names (88 level) on a status field
01 WS-ORDER-STATUS    PIC X(1).
   88 STATUS-PENDING  VALUE "P".
   88 STATUS-SHIPPED  VALUE "S".
   88 STATUS-COMPLETE VALUE "C".
   88 STATUS-CANCELED VALUE "X".

*> Numeric variables for type conversion examples
01 WS-NUM-STRING      PIC X(5)    VALUE "42".
01 WS-NUM-VALUE       PIC 9(5)    VALUE ZEROS.
01 WS-RESULT          PIC 9(7)V99 VALUE ZEROS.

PROCEDURE DIVISION.
    *> Display constants
    DISPLAY "Company:     " WS-COMPANY-NAME.
    DISPLAY "Pi:          " WS-PI.
    DISPLAY "Max retries: " WS-MAX-RETRIES.

    *> Use MOVE to convert alphanumeric string to numeric
    MOVE WS-NUM-STRING TO WS-NUM-VALUE.
    COMPUTE WS-RESULT = WS-NUM-VALUE * WS-PI.
    DISPLAY "42 * Pi =    " WS-RESULT.

    *> Set status and test with condition names
    MOVE "S"            TO WS-ORDER-STATUS.
    IF STATUS-SHIPPED
        DISPLAY "Order has shipped."
    END-IF.
    IF STATUS-COMPLETE
        DISPLAY "Order is complete."
    ELSE
        DISPLAY "Order is not yet complete."
    END-IF.

    STOP RUN.

Running with Docker

1
2
3
docker pull esolang/cobol:latest

docker run --rm -v $(pwd):/app -w /app esolang/cobol sh -c 'cobc -x -free variables-const.cob && ./variables-const'

Expected Output

Company:     CodeArchaeology
Pi:          3141593
Max retries: 05
42 * Pi =    000013194
Order has shipped.
Order is not yet complete.

Condition names are COBOL’s boolean type. Rather than using a separate boolean type, COBOL lets you attach named conditions to any variable’s possible values. IF STATUS-SHIPPED reads naturally and is far clearer than IF WS-ORDER-STATUS = "S" scattered through hundreds of paragraphs.


Key Concepts

  • PIC clauses define storage format9(5) means five decimal digits, X(20) means twenty alphanumeric characters. The format determines what values are valid.
  • V is an implied decimal point9(5)V99 stores seven digits but treats the last two as cents. No decimal character is stored; arithmetic uses the implied position.
  • S prefix enables signed numbers — Without S, a numeric variable cannot represent negative values.
  • Level numbers create hierarchy01 is the top level; items nested inside with higher numbers (05, 10, etc.) form group records equivalent to structs in other languages.
  • 88 condition names are COBOL booleans — Attach meaningful names to valid states of a variable; test with IF condition-name for readable, maintainable code.
  • ZEROS, SPACES, HIGH-VALUES are figurative constants — VALUE ZEROS initializes numerics to zero; VALUE SPACES initializes alphanumerics to spaces.
  • All variables live in DATA DIVISION — Unlike C, Java, or Python, COBOL does not allow variable declarations inside procedure code. Every data item is declared upfront.
  • MOVE handles type coercion — Moving an alphanumeric "42" into a numeric field converts the string to a number. COBOL does this implicitly on MOVE, but arithmetic directly on alphanumeric fields is an error.

Running Today

All examples can be run using Docker:

docker pull esolang/cobol:latest
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining