[SOLVED] Passed array Global or pointer ?

General FreeBASIC programming questions.
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

[SOLVED] Passed array Global or pointer ?

Post by exagonx »

Hi friends, writing a code this morning I got a doubt about pointers.

In the following code I have created a class with an array that is passed to a function and added some strings.

My question is whether the function stores data in the class array because it is considered public / global or because it treats it as a pointer.

Thanks for your attention

Code: Select all

type myclass
dim myarray(10) as string
dim index as integer
end type

declare function addrow( passarray() as string)as integer

function addrow( passarray() as string)as integer
	
	passarray(2) = "for sure"
	passarray(3) = "A beautyfull"
	passarray(4) = "World"
	
return 0
end function

dim cicle as integer
dim MC as myclass

MC.myarray(0) = "Hello"
MC.myarray(1) = "this is"

addrow( MC.myarray() )

for cicle = 0 to 4 step 1
print MC.myarray(cicle)

next cicle
Last edited by exagonx on Oct 20, 2021 12:55, edited 1 time in total.
fxm
Moderator
Posts: 12109
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passed array Global or pointer ?

Post by fxm »

An array is always passed by reference to a procedure (this is why none declaration specifier, like ByRef or ByVal, is specified in this case).
As a result, the procedure can not only read but also modify the array.

As an array is a complex object, passing the address of its data block is not sufficient as for a simple variable.
Under the hood, rather the address of a descriptor of the array is passed. This descriptor contains all the information about the array.
See the FBARRAY type at FBARRAY (array descriptor structure and access).
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: Passed array Global or pointer ?

Post by exagonx »

fxm wrote:An array is always passed by reference to a procedure (this is why none declaration specifier, like ByRef or ByVal, is specified in this case).
As a result, the procedure can not only read but also modify the array.

As an array is a complex object, passing the address of its data block is not sufficient as for a simple variable.
This means that in any case an array passed to a Sub or Function will always be treated as a pointer and not as an Array Object right?

The doubt arose to me because in C and C ++ it is necessary to use pointers in order to interact with an Array Object outside a function or Class.

Anyway Thank you very mutch.
fxm
Moderator
Posts: 12109
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passed array Global or pointer ?

Post by fxm »

We could more simply say that when an array is passed to a procedure, it is in fact (under the hood) its descriptor which is passed by reference to the procedure (passing its descriptor by reference allows to modify its characteristics as for example to resize dynamic arrays with 'Redim').
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Passed array Global or pointer ?

Post by caseih »

exagonx wrote:This means that in any case an array passed to a Sub or Function will always be treated as a pointer and not as an Array Object right?
No. From the point of view of your code, or syntax, an array passed to a sub or function is interacted with in the same way you would anywhere else. It is *is* the array, not a pointer to an array. It just happens that since it was passed by descriptor, it's not a copy of the array, not a pointer to an array, but the actual, original, array. If you insist on analogies to C or C++, it is more akin to pass by reference not pass by pointer.
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: Passed array Global or pointer ?

Post by exagonx »

caseih wrote:
exagonx wrote:This means that in any case an array passed to a Sub or Function will always be treated as a pointer and not as an Array Object right?
No. If you insist on analogies to C or C++, it is more akin to pass by reference not pass by pointer.
Allright now I understand

then like the code down if I use it like Global Var its almost the same thing

Code: Select all

dim MyArray(4) as string

function Myfun()as integer
	MyArray(0) = "My Text"
	return 0
end function

function MyAltFun(MyAr() as string)as integer
	MyAr(1) = "Alt My Text"
	return 0
end function

MyFun()
MyAltFun(MyArray())
print MyArray(0)
print MyArray(1)
fxm
Moderator
Posts: 12109
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passed array Global or pointer ?

Post by fxm »

dim shared MyArray(4) as string
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: Passed array Global or pointer ?

Post by exagonx »

fxm wrote:dim shared MyArray(4) as string
Yes Thank you for the correction
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: Passed array Global or pointer ?

Post by speedfixer »

If you wanted direct access to the data in the array without the other management by way of the descriptor, you could create a pointer to the first item in the array (update it any time the array changed) and use it directly.

It is a lot of work.
For multi-dimension arrays - a LOT more work.

But it is a choice.

david
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: Passed array Global or pointer ?

Post by exagonx »

speedfixer wrote:If you wanted direct access to the data in the array without the other management by way of the descriptor, you could create a pointer to the first item in the array (update it any time the array changed) and use it directly.

It is a lot of work.
For multi-dimension arrays - a LOT more work.

But it is a choice.

david
Apologies if I ask you but Can you make a fast example just for understand.
And thank you for the answer.
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: [SOLVED] Passed array Global or pointer ?

Post by speedfixer »

I can make an example. I WISH I could be fast. Just - unless needed - I don't do that any more.
One bad wife can do that to you, you know?

One example being brewed up as this is being posted.

david
exagonx
Posts: 315
Joined: Mar 20, 2009 17:03
Location: Italy
Contact:

Re: [SOLVED] Passed array Global or pointer ?

Post by exagonx »

speedfixer wrote: One bad wife can do that to you, you know?
david
Please don't want to be responsible for the fight between you and your wife.

Never let it be that you have to share the dog's bed
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: [SOLVED] Passed array Global or pointer ?

Post by speedfixer »

No ... won't happen. I shed *that* wife years ago.

Learned a little bit from that.
Maybe just enough to learn how to let me be trained by my new wife.
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: [SOLVED] Passed array Global or pointer ?

Post by speedfixer »

As promised:

Code: Select all

dim shared as string ptr p_data = 0
dim shared as boolean endprogram
dim shared as long tinput, conc, conr    ' for input start; rows/columns max

function keepstring(indata as string) as long
static as string helddata(0 to 20)  ' strings to hold
static as long count                ' count of items
dim as long result                  ' index to data
    if count > 19 then              ' update how many items held
        count = 0
        for ixi as integer = 1 to 20
            if len(helddata(ixi)) > 0 then count += 1    ' something is there
        next
        if count > 19 then return -99   ' flag that we have no more space
    end if
    for ixi as integer = 1 to 20
        if len(helddata(ixi)) = 0 then  ' nothing is there
            helddata(ixi) = indata : result = ixi     ' store the data
            exit for
        end if
    next
    p_data = @helddata(0)               ' update the pointer, just in case
    return result
end function                                                ' keepstring

function getstring(byref index as long) as string
dim as string result
dim as boolean remove
    if p_data = 0 then return "" ' nobody home, yet
    if (index > 20) or (index < -20) then return ""     ' error
    if index < 0 then                       ' flag to remove data
        index = -(index) : remove = true
    end if
    result = p_data[index]
    if len(result) = 0 then
        index = -99                         ' no data
    else
        if remove then p_data[index] = ""   ' index negative == remove the data
    end if
    return result
end function                                                ' getstring

function findstring(fdata as string) as long
dim as long result
    if p_data = 0 then return -99       ' nobody home, yet
    if len(fdata) = 0 then return -99       ' error
    for ixi as integer = 1 to 20
        if p_data[ixi] = fdata then
            result = ixi : exit for
        end if
    next
    return result
end function                                                ' findstring

function keyentry() as string       ' get/show key input
dim as string result, kdat
dim as integer prevrow, prevcol      ' integer, long? someday will be all right
    prevrow = csrlin : prevcol = pos
    do
        kdat = inkey                        ' get a key, if available
        if instr(chr(27), kdat) <> 0 then
            if len(result) = 0 then         ' this is clear or terminate
                result = chr(27)
            else
                result = ""
            end if
            locate tinput, 5, 0
            print "   "; space(len(result)); "   ";   ' clean input area
            exit do     ' cancel action, exit loop
        end if
        if len(kdat) <> 0 then          ' faster test if string is empty
            if instr(chr(10) & chr(13), kdat) <> 0 then   ' end of entry
                locate tinput, 5, 0
                print "   "; space(len(result)); "   ";  ' clean input area
                exit do
            else
                result = result & kdat ' catch the keys
            end if
        end if
        locate tinput, 5, 0 : print " " & result & "  ";   ' print clean input
        sleep 8, 1
    loop
    locate prevrow, prevcol             ' return to previous location
    return left(result, 15)             ' just to be a reasonable example
end function                                                ' keyentry

sub showdata(start as long)
dim as integer prevrow, prevcol      ' integer, long? someday will be all right
    if p_data = 0 then return       ' nobody home, yet
    prevrow = csrlin : prevcol = pos

    for ixi as integer = 1 to 20        ' show all data items and index
        locate ((start - 1) + ixi), conc - 21, 0 : print ixi;
        locate ((start - 1) + ixi), conc - 17, 0
        if len(p_data[ixi]) <> 0  then
            print p_data[ixi];
        else
            print space(conc - 17);
        end if
    next
    locate prevrow, prevcol         ' return to previous location
end sub ' showdata

' set up screen  ---------------------------
screen 18                           ' pick a screen
#if __FB_VERSION__ < "1.08"         ' new stuff, not well tested by me yet - dnb
    dim as integer shorz, svert, coffset : screeninfo shorz, svert  ' pixels
#else
    dim as long shorz, svert : screeninfo shorz, svert
#endif
width shorz\8, svert\16     ' my screen too big and letters too small
conc = loword(width()): conr = hiword(width)  ' total columns/rows

tinput = conr - 2           ' show input at bottom of screen
coffset = 14                ' print return message from left of center of screen

print : print " screen: high = "; conc; "  wide = "; conc : print
print " characters: i for input     index: d for delete       <ESC> to quit"
print "             f to find              r for retrieve"
' start of main loop  ----------------------
dim as long datastart = 8                   ' where to show data list
dim as boolean kpause
dim as string kkey, strdata : dim as long indexdata

locate ((datastart - 1)), conc - 23, 0
print "index       data"
do
    locate 1, 1, 0 :  print " ";            ' a 'home' for the cursor
    kkey = keyentry()                       ' get a function choice
    if kkey = chr(27) then exit do          ' terminate program
    kkey = lcase(kkey)
    select case kkey
        case "i"    ' input
            locate conr - 1, conc\2 - coffset, 0 : print "input";
            kkey = keyentry()
            if len(kkey) <> 0 then
                keepstring(kkey) : kpause = true
            end if
        case "r"    ' retrieve
            locate conr - 1, conc\2 - coffset, 0 : print "find";
            kkey = keyentry()
            if len(kkey) <> 0 then strdata = getstring(valint(kkey))
            locate conr - 1, conc\2 - coffset, 0
            print " data at index "; valint(kkey); ": "; strdata; "   (hit any key)";
        case "d"    ' delete
            locate conr - 1, conc\2 - coffset, 0 : print "delete";
            kkey = keyentry()
            if len(kkey) <> 0 then strdata = getstring(-(valint(kkey)))
            locate conr - 1, conc\2 - coffset, 0
            if len(strdata) = 0 then
                print kkey; " no data at"; valint(kkey); "   (hit any key)";
            else
                print " removed: '"; strdata; "'   (hit any key)";
            end if
        case "f"    ' find index
            locate conr - 1, conc\2 - coffset, 0 : print "find";
            kkey = keyentry()
            locate conr - 1, conc\2 - coffset, 0
            if len(kkey) <> 0 then indexdata = findstring(kkey)
            if indexdata > 0 then
                print "'"; kkey;"' found at index "; indexdata; "   (hit any key)";
            else
                if indexdata = -99 then
                    print "no data in data file to search  (hit any key)";
                else
                    print "'"; kkey; "' not found in data   (hit any key)";
                end if
            end if
        case else
            sleep 20, 1
            kpause = true
    end select
    showdata(datastart)
    if not kpause then
        while inkey <> "" : sleep 5,1 : wend ' clear
        while inkey = "" : sleep 50,1 : wend ' sleep
        while inkey <> "" : sleep 5,1 : wend ' clear ... who knows what might come next?
    end if
    locate conr - 1, conc\2 - coffset, 0 : print space(conc - (conc\2 - 9));
    kkey = "" : kpause = false
    sleep 20, 1
loop

' end of 'main' - time to exit
cls
print : print : print " program terminated" : print
' sometimes, with threads and complex input routines, input buffer for
'       use by sleep doesn't get cleared correctly - this always works
while inkey <> "" : sleep 5,1 : wend ' clear
while inkey = "" : sleep 10,1 : wend ' sleep
while inkey <> "" : sleep 5,1 : wend ' clear keys ... anything could come next
speedfixer
Posts: 606
Joined: Nov 28, 2012 1:27
Location: CA, USA moving to WA, USA
Contact:

Re: [SOLVED] Passed array Global or pointer ?

Post by speedfixer »

Regarding previous code:

I tried to make it small. I just can't leave something incomplete. Leftover from my teaching days, I think.

The topic - passed array Global or pointer: first line of code is the key. It points to the array to be stored in keepstring().
All other code uses that pointer.

Easiest way to see this program: reformat it to the way YOU like to see it.
I normally never put more than one statement on a line. I normally put way more blank lines for readability.
I normally keep all my debug code, blanked with #IFDEFs.

Yes, the array has an unused member at index 0. Comfortable for me; also, a habit for other reasons.

I tried to make a lot of comments and not be too verbose.

If any part is not clear or there is a question of why I did something the way I did: please ask.

david
Post Reply