COMP, BINARY and SYNC
COMP (also BINARY, COMP-4) stores a two's-complement binary
integer, the same format C, Java and the z/Architecture CPU use for
int. Sizes follow the digit count:
| Digits | Bytes | Mainframe name |
|---|---|---|
| 1–4 | 2 | halfword |
| 5–9 | 4 | fullword |
| 10–18 | 8 | doubleword |
z/OS is big-endian: the most significant byte comes first, so the
hex reads naturally. GnuCOBOL writes COMP big-endian too, which is why
the bytes below match what you'd see on the mainframe.
IDENTIFICATION DIVISION.
PROGRAM-ID. BINARY1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-HALF PIC S9(4) COMP VALUE +300.
01 WS-NEG PIC S9(4) COMP VALUE -1.
01 WS-FULL PIC S9(9) COMP VALUE +100000.
01 WS-STD PIC S9(4) COMP VALUE 9999.
01 WS-NATIVE PIC S9(4) COMP-5 VALUE 9999.
01 WS-PLAIN.
05 P-FLAG PIC X.
05 P-COUNT PIC S9(9) COMP.
05 P-CODE PIC X.
05 P-LEN PIC S9(4) COMP.
01 WS-ALIGNED.
05 A-FLAG PIC X.
05 A-COUNT PIC S9(9) COMP SYNC.
05 A-CODE PIC X.
05 A-LEN PIC S9(4) COMP SYNC.
PROCEDURE DIVISION.
DISPLAY "+300 X'" FUNCTION HEX-OF(WS-HALF) "'"
DISPLAY "-1 X'" FUNCTION HEX-OF(WS-NEG) "'"
DISPLAY "+100000 X'" FUNCTION HEX-OF(WS-FULL) "'"
ADD 1 TO WS-STD WS-NATIVE
DISPLAY "COMP 9999 + 1 = " WS-STD
DISPLAY "COMP-5 9999 + 1 = " WS-NATIVE
DISPLAY "PLAIN " FUNCTION LENGTH(WS-PLAIN) " BYTES"
DISPLAY "ALIGNED " FUNCTION LENGTH(WS-ALIGNED) " BYTES"
STOP RUN.
+300 X'012C'
-1 X'FFFF'
+100000 X'000186A0'
COMP 9999 + 1 = +0000
COMP-5 9999 + 1 = +10000
PLAIN 8 BYTES
ALIGNED 12 BYTES
Picture vs. capacity
A halfword can hold up to 32,767, but PIC S9(4) promises four digits.
Which one wins depends on the IBM compiler option TRUNC:
TRUNC(STD): results are cut to the picture.9999 + 1gives0000. GnuCOBOL behaves like this by default.TRUNC(BIN): the full binary range is kept. Slower, but safe when the value comes from a non-COBOL program or a system API.TRUNC(OPT): the compiler does whatever is fastest. Code must never exceed the picture.
COMP-5 means native binary regardless of TRUNC. Use it for values
exchanged with C, Java, or system services such as lengths returned by
an API.
SYNC and slack bytes
The hardware reads binary fields fastest when a fullword starts on an
address divisible by 4 and a halfword on one divisible by 2. SYNC
(SYNCHRONIZED) asks the compiler to align the field, inserting unnamed
slack bytes before it. Above, WS-ALIGNED grew from 8 to 12 bytes:
3 slack bytes after A-FLAG and 1 after A-CODE.
Modern z/Architecture handles unaligned data well, so SYNC is rare in
new code. It matters when a record layout must match something that
was aligned, such as a control block or a file written by an old
program. Miss a slack byte and every following field shifts.
Where binary fields turn up
Counters, subscripts and lengths in working storage; record-length
and count fields in file headers; RETURN-CODE; Db2 SMALLINT and
INTEGER columns (S9(4) COMP and S9(9) COMP); CICS EIBCALEN.
Money almost never. That's packed decimal's job.
On the job
In ISPF HEX mode a binary field has no sign nibble and no digits you
can read directly. Convert it: X'000186A0' is 1×65536 + 134×256 +
160 = 100,000. A hex calculator is a normal part of the toolkit.