× 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.



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 ...

Replies:

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.