× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



If you are getting that big, I would be looking at a User Index. That's what 
they are designed for. 

-----Original Message-----
From: Scott Klement [mailto:rpg400-l@xxxxxxxxxxxxxxxx]
Sent: Tuesday, March 29, 2005 10:47 AM
To: RPG programming on the AS400 / iSeries
Subject: Re: Arrays


Hello,

> In using VB and C I have the ability to dynamically increase an array's size
> from say 50 to 100 without losing the existing data, is this possible in
> RPG?

RPG protects you from errors with validity checking, C does not. For 
example, what's wrong with this C code?

        int test[10];
        int x;

        for (x=1; x<=10; x++) {
             test[x] = x;
        }

At first glance it looks like it might even be valid -- but it's not. 
This simple code will write data past the end of the array, causing 
memory corruption!  Neither the compiler nor the runtime will catch 
mistakes like this because it doesn't do any bounds checking on the array 
index.  You could referrence test[500] if you wanted, it wouldn't report 
any error, it'll just happily corrupt memory.

RPG is smarter than that.  If you declare an array with 10 elements, it'll 
only let you access those 10!  The following program will crash when it 
tries to access test(11):

      D test            s             10I 0 dim(10)
      D x               s             10I 0

      c                   for       x = 2 to 11
      c                   eval      test(x) = x
      c                   endfor

So that's a GOOD thing because mistakes are found when the code is tested, 
rather than random errors that are hard to track down because they only 
occur sporadically.

At first glance you might be thinking "but, that means that I can't do 
dynamic arrays!" Indeed, in C you could do the following:

        int *test;
        int maxelem;
        int x;

        maxelem = 10;
        test = malloc((maxelem+1) * sizeof(int));

        for (x=1; x<=maxelem; x++) {
             test[x] = x;
        }

        maxelem = 20;
        test = realloc(test, (maxelem+1) * sizeof(int));

        for (; x<=maxelem; x++) {
             test[x] = x;
        }

        free(test);

And that'll work, because there's no bounds checking on the array, so you 
can change the number of elements in it at any time, and it'll let you 
access those elements.  You can do the same thing in RPG, but in order to 
do so, you must declare the array with the MAXIMUM number of elements 
you'll ever use.  That way, the system won't stop you from accessing 
them... best of both worlds:

      D int             s             10I 0
      D p_test          s               *
      D test            s                   dim(32767)
      D                                     like(int)
      D                                     based(p_test)
      D max             s             10I 0
      D x               s             10I 0

      c                   eval      max = 10
      c                   eval      p_test = %alloc(%size(int) * max)
      c                   for       x = 1 to max
      c                   eval      test(x) = max
      c                   endfor

      c                   eval      max = 20
      c                   eval      p_test = %realloc( p_test
      c                                              : %size(int) * max)
      c                   dow       x < max
      c                   eval      x = x + 1
      c                   eval      test(x) = max
      c                   enddo

      c                   dealloc                 p_test

Basically, declaring the array out to 32767 elements gives you the same 
sort of flexibility that C has, you can use any number you like. Since the 
array is BASED, it only uses as much memory as you've allocated, anyway.

Of course, the one problem that remains is when you need to handle more 
than 32767 elements!  At this point, you might start considering whether 
an array is the right tool for the job. Other people have suggested 
embedded SQL and work files, both good suggestions.

If you do decide to stay with an array, you can do that, too... well, sort 
of.  Stop and consider what an array is -- it's merely a spot in memory 
where there are many fields of the same type repeating.  test(1) is 
immediately followed by test(2), which is followed by test(3), etc.  Under 
the covers the system says "hmm... he wants element #12. Since each 
element is 4 bytes long, that means he wants to look at bytes 45-48!"

Well, okay, the CPU probably doesn't actually say "hmm"

You can do that logic manually, as well. When you do that, you completely 
eliminate array bounds checking, so you can make your array as large as 
you want.  It's called pointer math :)

      H DFTACTGRP(*NO)

      D SetArrayPos     PR
      D   Index                       10I 0 value

      D max             s             10I 0
      D p_test          s               *
      D p_elem          s               *
      D elem            s             10I 0 based(p_elem)
      D max             s             10I 0
      D x               s             10I 0

      c                   eval      max = 10
      c                   eval      p_test = %alloc(%size(elem) * max)
      c                   for       x = 1 to max
      c                   callp     SetArrayPos(x)
      c                   eval      elem = x
      c                   endfor

      c                   eval      max = 20
      c                   eval      p_test = %realloc( p_test
      c                                              : %size(elem) * max)
      c                   dow       x < max
      c                   eval      x = x + 1
      c                   callp     SetArrayPos(x)
      c                   eval      elem = max
      c                   enddo

      c                   dealloc                 p_test

      c                   eval      *inlr = *on

      P SetArrayPos     B
      D SetArrayPos     PI
      D   Index                       10I 0 value
      c                   eval      p_elem = p_test
      c                                    + (Index-1) * %size(Elem)
      P                 E

Using that approach, you're still limited to 16mb of space, but changing 
the code to use TS_malloc() and TS_realloc() (instead of %alloc and 
%realloc) would make it possible to bypass that limit as well.

The only thing I'd like to caution you on if you use these techniques is 
that %realloc (or TS_realloc or the REALLOC op-code... whatever) actually 
allocates a new spot in memory and copies the data to it.  (If you've done 
this in C, you should already know that!) You should take care to keep the 
re-allocating to a minimum. Maybe allocate 1000 elements at a time or 
something like that so that so that the code doesn't spend TOO much time 
copying stuff in around in memory.

Good luck






As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.