• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Thinking In Pointers

    September 11, 2013 Ted Holt

    Suppose you were to ask me how large an alphanumeric variable should be, and I replied that I didn’t know, nor did I care. Wouldn’t that sound odd? Those of us who have been programming in business languages such as RPG, COBOL, and CL since the French and Indian War always think it’s important to know the size of a variable, otherwise we won’t be able to define it properly in a program. But when you work with pointers, a variable’s defined size doesn’t necessarily matter. Let me show you what I’m talking about.

    Consider a command:

    CMD        PROMPT('Do something')
    PARM       KWD(OBJECT) TYPE(*CHAR) LEN(10) MAX(12) +
                 EXPR(*YES) PROMPT('List of objects')
    

    Here’s the parameter list of the CL command-processing program.

    pgm parm(&inList)
    

    How long must &inList be? At least 122 bytes, in order to allow for a maximum of 12 elements. The first two bytes contain a binary number, the value of which is the number of elements in the list. The remainder of the parameter consists of 10-byte values. Twelve times 10 bytes per element of the list, plus two bytes for the binary prefix, is 122.

    pgm parm(&inList)
    
       dcl    &inList     *char   122
    

    The command processor may send 122 bytes to the program, or it may send fewer than 122 bytes. For instance, if the user keys in three object names, the command processor will send 32 bytes to the program, and it is important that the program not access the memory assigned to bytes 33 through 122.

    Here is the not-quite-complete command-processing program, written in CL.

    pgm parm(&inList)
       dcl    &inList        *char   122
    
       dcl    &Ndx           *int    2
       dcl    &ListSize      *int    2
       dcl    &Offset        *int    2
       dcl    &CurElement    *char  10
    
       chgvar &ListSize      %bin(&inList 1 2)
       chgvar &Offset        3
    
       dofor  &Ndx from(1) to(&ListSize)
           chgvar &CurElement    %sst(&inList &Offset 10)
    
           /* do something with &CurElement */
    
           chgvar &Offset        (&Offset + 10)
       enddo
    

    Each iteration of the DOFOR loop retrieves the next list value into variable &CurElement. The program does something with &CurElement, but whatever it does is irrelevant to this discussion.

    One day someone decides that 12 occurrences are not enough. You double the value of the MAX parameter, to 24.

    CMD        PROMPT('Test list processing')
    PARM       KWD(OBJECT) TYPE(*CHAR) LEN(10) MAX(24) +
                 EXPR(*YES) PROMPT('List of names')
    

    Now you have to modify the CL program. Let’s see. The &inList variable must be assigned the value of 24 times 10, plus 2, or 242.

    Now permit me to encourage you to think about programming in a way you may not be accustomed to. (This may be analogous to asking a native speaker of English to think in Chinese, but bear with me.)

    When we process the list, how many bytes of the list do we care about at any one time? The answer is 10. We never care about more than 10 bytes at any one time.

           chgvar &CurElement    %sst(&inList &Offset 10)
    
           /* do something with &CurElement */
    

    So why define a 122-byte variable when 10 bytes will suffice? Look at this version of the same command-processing program.

    pgm parm(&inList)
    
       dcl    &inList        *char   1
    
       dcl    &pInList       *ptr
       dcl    &ListSize      *int    2  stg(*based) basptr(&pInList)
       dcl    &pElement      *ptr
       dcl    &CurElement    *char  10  stg(*based) basptr(&pElement)
       dcl    &Ndx           *int    2
    
       chgvar &pInList             %addr(&inList)
       chgvar &pElement            &pInList
       chgvar %offset(&pElement)  (%offset(&pElement) + 2)
    
       dofor  &Ndx from(1) to(&ListSize)
    
           /* do something with &CurElement */
    
           chgvar %offset(&pElement)  (%offset(&pElement) + 10)
       enddo
    

    The &inList variable has been defined with a length of 1, which is clearly and incontrovertibly inaccurate. I’ve defined it that way because I don’t care what the length of the complete list is. All I care about is the parameter’s address in memory.

    Notice that I’ve defined two pointer variables–&pInList and &pElement. Let’s look at the role of &pInList first.

    The first Change Variable (CHGVAR) command sets &pInList to the memory address of parameter &inList. Since variable &ListSize is based on &pInList, &ListSize also points to the area of memory where the list begins. Since the first two bytes of the parameter contain the number of elements in the list, the value of &ListSize, then, is the number of elements in the list.

    The values in the list begin in position three of the list, so that’s the reason for the next two CHGVAR commands. Since &CurElement is based on &pElement, the value of &CurElement is the value of the first value in the list when the DOFOR begins. Each iteration of the loop advances the &pElement 10 bytes, which makes &CurElement overlay the next element in the list.

    At the risk of belaboring the point, here’s my attempt at an illustration.

    Suppose someone runs this command as follows:

    DOIT OBJECT(SQUEEZLE PUCKERT SNOOFLE GRIPPICK)
    

    Suppose also that the system loads the list into memory at address 101. Here are the contents of memory.

    Address

    Value

    101 – 102

    0004

    103 – 112

    SQUEEZLE

    113 – 122

    PUCKERT

    123 – 132

    SNOOFLE

    133 – 142

    GRIPPICK

    Variable &pInList is 101. At the beginning of each iteration of the loop, &pElement has the values 103, 113, 123 and 133.

    And what change must be made to this program when the MAX value in the command is increased from 12 to 24? Why, none at all! Is that fine, or what?

    By the way, if this example looks familiar, you may have seen it in an article I wrote about RPG and basing pointers. See the Related Story below for details.

    Pointers are unfamiliar territory to many programmers, but they don’t have to be. Learn to use them. Besides being useful, they’re also fun!

    RELATED STORY

    Basing Pointer Variables in RPG: The Basics



                         Post this story to del.icio.us
                   Post this story to Digg
        Post this story to Slashdot

    Share this:

    • Share on Reddit (Opens in new window) Reddit
    • Share on Facebook (Opens in new window) Facebook
    • Share on LinkedIn (Opens in new window) LinkedIn
    • Share on X (Opens in new window) X
    • Email a link to a friend (Opens in new window) Email

    Tags:

    Sponsored by
    JAMS Software

    One Scheduler. IBM i, Windows, Linux, and More.

    IBM i teams trust JAMS to schedule and orchestrate jobs across every platform in their environment. Centralized visibility, cross-platform dependency management, and alerts that reach the right person before the business feels it.

    Fewer than 5% of IBM i shops run IBM i only. The rest are managing cross-platform dependencies — often without a clear picture of how they connect. JAMS draws that map, enforces those dependencies automatically, and gives your team a single place to monitor, manage, and recover when something goes wrong.

    If you are running hundreds of CL scripts and custom RPG processes, bring them as-is. JAMS runs them exactly as they do today — except now they are visible, monitored, and part of an orchestrated workflow instead of scattered across folders only one person knows about.

    No consumption-based pricing. No surprise bills when your workload spikes. You pay based on how many machines JAMS talks to — that’s it.

    Learn More → https://jamsscheduler.com/lp/ibm-i

    Share this:

    • Share on Reddit (Opens in new window) Reddit
    • Share on Facebook (Opens in new window) Facebook
    • Share on LinkedIn (Opens in new window) LinkedIn
    • Share on X (Opens in new window) X
    • Email a link to a friend (Opens in new window) Email

    Sponsored Links

    Maxava:  FREE Webinar: Test your DR without Downtime. September 12
    Shield Advanced Solutions:  HA4i ~ High Availablity for the IBM i. FREE 30-day trial
    System i Developer:  Upgrade your skills at the RPG & DB2 Summit in Minneapolis, Oct 15-17.

    More IT Jungle Resources:

    System i PTF Guide: Weekly PTF Updates
    IBM i Events Calendar: National Conferences, Local Events, and Webinars
    Breaking News: News Hot Off The Press
    TPM @ The Reg: More News From ITJ EIC Timothy Prickett Morgan

    Retrieve The Call Stack In DB2 For i Admin Alert: Six Tips For Managing IBM i Spooled File Storage

    Leave a ReplyCancel reply

Volume 13, Number 17 -- September 11, 2013
THIS ISSUE SPONSORED BY:

SEQUEL Software
WorksRight Software
American Top Tools

Table of Contents

  • Retrieve The Call Stack In DB2 For i
  • Thinking In Pointers
  • Admin Alert: Six Tips For Managing IBM i Spooled File Storage

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • The Power11 IBM i P05 Entry Machine Finally Arrives
  • Big Blue Finally Unveils First IBM i Tech Refreshes Of 2026
  • Guru: Analyzing User Session Statistics, Part 1
  • Relion Solutions Launches With A Focus On Customer Service
  • IBM i PTF Guide, Volume 28, Numbers 23 And 24
  • Big Blue Ships Bob 2.0 And Premium Package For IBM i
  • Your IBM i Jobs Don’t Live On An Island Anymore
  • FalconStor Creates Cloud Clean Room To Prove Backup Recoveries Work
  • Talking Git On IBM i With A Bunch Of IBM i Gits
  • IBM i PTF Guide, Volume 28, Number 22

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle