IonicWind Software

IWBasic => General Questions => Topic started by: Andy on November 12, 2015, 06:22:31 AM

Title: Pointers
Post by: Andy on November 12, 2015, 06:22:31 AM
Hi everyone,

After my failed attempt at using pointers, i'ts time to go back to basics whith this one.

Firstly, I don't use them, but would like to understand them better.

So, here is my first question....

Why when I define a udt as:

TYPE MYUDT
    def across as int
    def down as int 
    DEF name as STRING
ENDTYPE

DEF pUdt as POINTER

pUdt = NEW(MYUDT,100)

I only get the first letter of the strings or no letter at all, code here...


int y

TYPE MYUDT
    def across as int
    def down as int 
    DEF name as STRING
ENDTYPE

DEF pUdt as POINTER

pUdt = NEW(MYUDT,500)

SETTYPE pUdt, MYUDT

#pUdt.name[1] = "First entry."
#pUdt.name[2] = "Joe Smith"
#pUdt.name[3] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#pUdt.name[4] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
#pUdt.name[5] = "cccccccccccccccccccccccccccccccccccccccccccccc"
#pUdt.name[6] = "dddddddddddddddddddddddddddddddddddddddddddddd"
#pUdt.name[7] = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
#pUdt.name[8] = "ffffffffffffffffffffffffffffffffffffffffffffff"
#pUdt.name[9] = "gggggggggggggggggggggggggggggggggggggggggggggg"
#pUdt.name[10] = "Last entry."


openconsole
print

for y = 1 to 10
#pUdt.across[y] = y
#pUdt.down[y]   = y
   print y," = ",#pUdt.name[y]," - ",#pUdt.across[y],#pUdt.down[y]
next y

do:until inkey$ <> ""
closeconsole

DELETE pUdt

end


When I chage the string definition to...

TYPE MYUDT
    def across as int
    def down as int 
    DEF name[1] as STRING
ENDTYPE

or

TYPE MYUDT
    def across as int
    def down as int 
    DEF name[255] as STRING
ENDTYPE

i.e. any number,the program displays the full strings:

"aaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbb" etc.

Why?

Thanks,
Andy.




Title: Re: Pointers
Post by: Egil on November 12, 2015, 09:06:42 AM
I have almost no experience using pointers myself, but some years ago Allan, who also is a member of this forum, posted this explanation on the MiniBASIC Forum:

Quote
RE: Need POINTER help  

Pointers are not difficult once they are understood.

I see them as a variable just like the other types. INT, UINT, FLOAT, CHAR, STRING, POINTER.

INT has numbers that can be negative or positive,
UINT has positive numbers
FLOAT has decimal numbers
CHAR has character
STRING has text
POINTER has Address.

INT num = 12 ' compiler puts 12 in the num variable - Num has an address in memory

POINTER ptr
ptr = &num

ptr holds an address - the address where Num is in memory,

PRINT num will print 12 as the compiler obtains the Address of num and retrieves the value.

PRINT #<INT>ptr will print 12 as the compiler will obtain the address stored in ptr and use it to go to num address rand retrieve the value.

That is how I look at pointers to understand how they work.
They really hold an address in memory.  


Hope this can help you solvle  your problems.


Egil
Title: Re: Pointers
Post by: LarryMc on November 13, 2015, 12:11:10 AM
Andy
You are not using pointers properly.
It's sort of like you are comparing apples to oranges to peaches.
It's 1AM here now(I've been spending too much time with my new toy...a CNC machine.. and I'm going to bed)
Tomorrow I will explain(as best I can) what you are doing wrong and why it is causing you to see what you are seeing.
Title: Re: Pointers
Post by: ckoehn on November 13, 2015, 09:06:36 AM
This is probably wrong, but here goes...

Take this for instance:

TYPE MYUDT
   int across
   int down
   string name 'allots a 254 char array
ENDTYPE

pointer p 'same as DEF p as pointer, this is less typing
MYUDT mUDT 'same as DEF mUDT as MYUDT

p=mUDT   'p is pointing to the mUDT variable, this is what the help file says.
'p=&mUDT 'this is what I would have thought it should be.  & means "address of".

'According to the help file this SHOULD work
SETTYPE p, MYUDT 'let pointer know what type

int curAcross, curDown 'variables to
string mystring '

curAcross=#p.across
curDown=#p.down
mystring=#p.name

DELETE p 'Delete pointer

I made some changes after I read the help file.. :-[

Later,
Clint

P.S.  I would like to see LarryMc explaination.
Title: Re: Pointers
Post by: LarryMc on November 13, 2015, 11:32:57 AM
Before I get too far along in this let me say it took me a long, long time to accept the phrase " pointers are your friend ".  With pointers I have been able to do some things I would not have been able to do otherwise; like build IWB+ for one. Secondly, I am NOT an expert when it comes to pointers. I manage to figure out enough to do what I want to get done with them and that's about it.  That being said, my following explanation may not be pure text book in every case but it is in words that allows me to functionally understand what is going on and use pointers and I hope it will do the same for some of you.

I'll start with the simplest variation of the problem presented by Andy and picked up by Clint and build from there.
TYPE MYUDT
    int across
    int down
    string name 'allots a 254 char array
ENDTYPE

pointer p 'same as DEF p as pointer, this is less typing
MYUDT mUDT 'same as DEF mUDT as MYUDT

p=mUDT   'p is pointing to the mUDT variable, this is what the help file says.
'p=&mUDT 'this is what I would have thought it should be.  & means "address of".

'p=&mUDT      'this is what I would have thought it should be.  & means "address of".
Clint made the above comment - the reason we don't use this version of the statement is
because structure type variables are passed by reference(pointer to their memory location)
The same would be true if our variable was one of the string types

'According to the help file this SHOULD work
SETTYPE p, MYUDT 'let pointer know what type

SETTYPE is optional but it will sure save a bunch of typing
if you don't use it then everywhere you refer to the 'p' pointer you will have to type
   #<MYUDT>p.
if you do use it then can get by with typing
   #p.
like I said, it can save a lot of typing. There are some rules in using it.
SETTYPE has to be executed before any reference to the pointer is made.
The SETTYPE has to be re-executed across subroutine and module(file) boundaries.

int curAcross, curDown 'variables to
string mystring '

curAcross=#p.across
curDown=#p.down
mystring=#p.name

DELETE p 'Delete pointer

It is very important that when you are through with a pointer that you clean up memory.
Failure to do this will cause a "memory leak".
What I'm not sure of is whether or not DELETE is required for pointers that,
like this example, don't involve the NEW command.
I don't think it is required here but it doesn't hurt.

so, for a working example:

Compile as a Console Exec
TYPE MYUDT
    int across
    int down
    string name 'allots a 254 char array
ENDTYPE

pointer p 'same as DEF p as pointer
MYUDT mUDT 'same as DEF mUDT as MYUDT

p = mUDT    'p is pointing to the mUDT variable

SETTYPE p, MYUDT 'let pointer know what type

#p.across = 34
#p.down = 123
#p.name = "John Brown"

print
    print #p.across,#p.down," ",#p.name
print
print "Press any key to quit"

waitcon

DELETE p
end


I'll build upon this example in the next installment
Title: Re: Pointers
Post by: ckoehn on November 13, 2015, 01:03:20 PM
Thanks LarryMc for your explanation. Makes sense to me.

I either didn't know or forgot that structure types were passed by reference like string types were.

Waiting for the next installment...

Later,
Clint
Title: Re: Pointers
Post by: LarryMc on November 13, 2015, 08:21:47 PM
The next step we'll take in expanding our little sample program in the direction of Andy's original post is
the use of the NEW command

In the previous sample program we had this line
p = mUDT
we're now going to change it to
p = NEW(MYUDT,5)
--we no longer need this line
MYUDT mUDT
so it can be removed--
By definition when we use the NEW command in this manner we defining an array (p) of 5 pointers that point to 5 mUDT structures.
remembering that arrays are indexed starting at 0 we can initialize  the contents of our 5 structures
with the following routine:
int x
for x = 0 to 4
   #p[x].across = 34 + x
   #p[x].down = 123 + x
   #p[x].name = "John Brown"+str$(x)
next x

then to print the contents
for x = 0 to 4
   print #p[x].across, #p[x].down," ", #p[x].name
next x


so, for a working example:

Compile as a Console Exec
TYPE MYUDT
    int across
    int down
    string name 'allots a 254 char array
ENDTYPE

pointer p 'same as DEF p as pointer
MYUDT mUDT 'same as DEF mUDT as MYUDT

p = NEW(MYUDT,5)    'p is pointing to the mUDT variable

SETTYPE p, MYUDT 'let pointer know what type

int x
for x = 0 to 4
   #p[x].across = 34 + x
   #p[x].down = 123 + x
   #p[x].name = "John Brown"+str$(x)
next x

print
for x = 0 to 4
   print #p[x].across, #p[x].down," ", #p[x].name
next x
print
print "Press any key to quit"

waitcon

DELETE p
end


We'll build upon this example in the next installment
Title: Re: Pointers
Post by: Andy on November 14, 2015, 03:24:06 AM
Good explanation Larry thanks for taking your time to post it,
I now see why I was getting the array side of things wrong.

Andy.
Title: Re: Pointers
Post by: Andy on December 05, 2015, 03:44:01 AM
The above example is very good, and I have got it with pointers now.

But here is a question:
The above example is working with a UDT, and  
#p[x].name = "John Brown" - works.

When I'm using a fixed type STRING I have to use this notation:
#<STRING>astring[0,0] = "First"

Where [0 = entry / index number and 0] for the characters in the string.

I would have thought that maybe
#p[x].name = "John Brown"  

should be...
#p[x,0].name = "John Brown" ?

#p[x,0].name = "John Brown" does actually work, I can only assume the compiler "knows" that .name is a string and essentially does the same thing as #p[x,0] ?

Anyway it's just a question, and I'm happy with both:
#p[x,0].name = "John Brown AND
#<STRING>astring[0,0] = "First"

It's just the difference in notation between fixed type and udt I was wondering about and I will have to remember it.

Thanks,
Andy.



Title: Re: Pointers
Post by: LarryMc on December 05, 2015, 06:24:13 AM
Don't confuse the two.
think of it this way (which may not be technically correct but it's the way I keep it straight)
pointers to string arrays are handled the way they are because there has to be a way to distinguish between single and multi dimension arrays AND varying lengths
that's the first part that we learned from the previous discussion.

now with a UDT's things are just a bit more complicated(or can be)

let's start easy
TYPE MYUDT
    int a
    string name
ENDTYPE

pointer p
MYUDT mUDT

p = NEW(MYUDT,5)
SETTYPE p, MYUDT

int x
for x = 0 to 4
   #p[x].a = 34 + x
   #p[x].name = "John Brown"+str$(x)
next x

print
for x = 0 to 4
   print #p[x].a, " ", #p[x].name
next x
print
print "Press any key to quit"

waitcon

DELETE p
end

that's basically the same as we did before
now, let's make our 'a' element an array of 5 int
and things will look like this
TYPE MYUDT
    int a[5]
    string name
ENDTYPE

pointer p
MYUDT mUDT

p = NEW(MYUDT,5)
SETTYPE p, MYUDT

int x
for x = 0 to 4
   for y=0 to 4
      #p[x].a[y] = 34 + x+y
   next y
   #p[x].name = "John Brown"+str$(x)
next x

print
for x = 0 to 4
   for y = 0 to 4
      print #p[x].a[y],
   next y
   print " ", #p[x].name
next x
print
print "Press any key to quit"

waitcon

DELETE p
end

The thing to note is that the array index "x" has nothing to do with the index 'y'.
In other words what happens on the left side of the "." is the parent and on the right side is the child.
With that in mind we'll go back and change our structure back so 'a' is a simple int but we'll make  name a pointer to an STRING

TYPE MYUDT
    int a
    POINTER name
ENDTYPE
/*SEE IF YOU CAN FIGURE IT OUT FROM HERE----I'M GOING TO BED  ;D */
pointer p
MYUDT mUDT

p = NEW(MYUDT,5)
SETTYPE p, MYUDT

int x
for x = 0 to 4
   #p[x].a = 34 + x
   #p[x].name = "John Brown"+str$(x)
next x

print
for x = 0 to 4
   print #p[x].a, " ", #p[x].name
next x
print
print "Press any key to quit"

waitcon

DELETE p
end

Title: Re: Pointers
Post by: Andy on December 06, 2015, 01:44:52 AM
Larry,

Thanks for all that, especially late at night!

Managed to read the strings:


string Text

TYPE MYUDT
    int a
    pointer name
ENDTYPE
/*SEE IF YOU CAN FIGURE IT OUT FROM HERE----I'M GOING TO BED  ;D */
pointer p
MYUDT mUDT

p = NEW(MYUDT,5)
SETTYPE p, MYUDT

int x
for x = 0 to 4
   #p[x].a = 34 + x
   #p[x].name = "John Brown"+str$(x)
next x

openconsole
print

for x = 0 to 4
   print #p[x].a, " ", #p[x].name
   Text = GetTheString(#p[x].name)
   print "Actual string is - ",Text
   print
next x

print
print "Press any key to quit"
waitcon

DELETE p
end

SUB GetTheString(pointer ToTheString),string
    string ActualString
    ActualString = #<string>ToTheString
RETURN ActualString
ENDSUB


I had to do that in a sub routine.

Title: Re: Pointers
Post by: Andy on December 06, 2015, 04:09:21 AM
I can also do it this way:

   pointer apointer
   apointer = #p[x].name
   print #<string>apointer


But not:
   print #<string>#p[x].name







Title: Re: Pointers
Post by: LarryMc on December 06, 2015, 07:36:20 AM
And the answer is ( drum roll......)
TYPE MYUDT
    int a
    pointer name
ENDTYPE
/*SEE IF YOU CAN FIGURE IT OUT FROM HERE----I'M GOING TO BED  ;D */
pointer p

p = NEW(MYUDT,5)
SETTYPE p, MYUDT

int x
string temp
for x = 0 to 4
   #p[x].a = 34 + x
temp = "John Brown"+str$(x)
/* the 'temp' variable is used to allocate memory for the string and get rid of the following warning
Warning: Temporary string assigned to POINTER, possible memory loss
*/
   #p[x].name = temp
next x

openconsole
print

for x = 0 to 4
   print #p[x].a, " ", #p[x].#<string>name   '<== name is a pointer so you have to tell it what type of data it contains
   print
next x

print
print "Press any key to quit"
waitcon

DELETE p
end


Title: Re: Pointers
Post by: Andy on December 06, 2015, 10:14:56 PM
Well that pulled a rabbit out of the hat.

Just one problem...

for x = 0 to 4
  print #p[x].a, " ", #p[x].#<string>name
  print
next x


Prints "a" correctly i.e. 34, then 35, and all the way up to 38.

"name" just returns "John Brown 4" five times? instead of
"John Brown 0"
"John Brown 1"
"John Brown 2" etc.

I changed the FOR to go to 3 instead of 4, and now it just prints
John Brown 3, so it's only ever printing the last string x number of times.

I can work out so far, the pointer remains the same, so all instances of "John Brown (x)" are being saved to the same memory location (the one for "temp").

If you change the code to:
int x
string temp[5]
openconsole

for x = 0 to 4
  #p[x].a = 34 + x
temp[x] = "John Brown"+str$(x)
  #p[x].name = temp[x]
next x


it works because each "temp x"  has a unique memory location.

Thanks,
Andy.

Title: Re: Pointers
Post by: LarryMc on December 07, 2015, 06:48:58 AM
you got it "Toyota"  ;D
Title: Re: Pointers
Post by: Andy on December 07, 2015, 07:04:22 AM
You're a good teacher Larry!

;D

Andy.
:)
Title: Re: Pointers
Post by: LarryMc on December 07, 2015, 07:10:03 AM
we're still not through, though.

you hard coded (predefined)the 'temp' array

can you figure out how to do it defining the temp array with the NEW command?
Title: Re: Pointers
Post by: Andy on December 07, 2015, 09:06:04 PM
Larry,

I did wonder why you added string called temp when we were talking about pointers.

So hopefully this is the right answer:

POINTER temp
temp = NEW(string,5)

openconsole

for x = 0 to 4
   #p[x].a = 34 + x
   #temp[x,0]= "John Brown"+str$(x)
   #p[x].name = #temp[x,0]
   print #p[x].name
next x


and DELETE temp at the end.

Also, with the print command added, I can see pointers have a "gap" of 255 which is the correct amount of "space" for a string.

Andy.
:)



Title: Re: Pointers
Post by: LarryMc on December 08, 2015, 12:18:22 AM
POINTER temp
temp = NEW(string,5)

openconsole

for x = 0 to 4
   #p[x].a = 34 + x
   #<string>temp[x,0]= "John Brown"+str$(x)
   #p[x].#<string>name = #<string>temp[x,0]
   print #p[x].#name
next x
'.....

DELETE temp
Title: Re: Pointers
Post by: Andy on December 08, 2015, 05:15:03 AM
Okay, I added the SETTYPE command to the code because....

QuoteSETTYPE is optional but it will sure save a bunch of typing
if you don't use it then everywhere you refer to the 'p' pointer you will have to type
  #<MYUDT>p.
if you do use it then can get by with typing
  #p.
like I said, it can save a lot of typing.

settype temp,string

And then did away with the <STRING> references, the program worked as it did before.

As far as my two brain cells allow me to try and understand the example we are talking about....

#p[x].name = #temp[x,0]

means to me, the string "John Brown 0" is placed in memory starting at "p
Title: Re: Pointers
Post by: LarryMc on December 08, 2015, 08:17:59 AM
1st, the line in my previous post where there was a missing <string> before name was a typo on my part.

Aside from that typo, look carefully at your code you posted in your last post.

What can we learn from it?

In our structure we have defined two variables:
"a" with a type of "int".
"name" with a type of "pointer".

Then we have this line
p = NEW(MYUDT,5)
What exactly have we done at that point.
We've set aside memory to hold 5 copies of our structure and placed the starting location of that memory in p.
how much memory did we set aside?
well INT's take 4 bytes each so that's 20 bytes and pointers also take 4 bytes so that's another 20 for a  total of 40 bytes.

we know we want to use "name" to store string data but we sure have created enough memory for that yet.
you already know very well about string data being shuffled around by its memory address via a pointer.
but our extra pointer has thrown a monkey wrench in the works
If you look at your code there is no where that memory is being set aside for the string data to be stored in "name".
There's no NEW statement and to be honest I don't have a clue as to how to create a nested NEW statement to handle the structure itself and then a pointer to a variable inside the structure.

So the overall lesson to learn from this last little exercise is don't put POINTERs in structures unless you are using it just to just to pass a pointer created in one placed to another place.  And even then you'd probably be better served by making the POINTER a global variable.

That's my semi-skilled opinion anyway.
Title: Re: Pointers
Post by: Andy on December 08, 2015, 09:01:12 PM
Larry,

Thanks for your time on pointers.

Making name a pointer really threw me I must say.

I'ts a good lesson about not using pointers in a structure.

For my part, I will stick with ints and strings etc, I find that is mainly all I need, and I can my head around them.

Thanks again,
Andy.
:)



Title: Re: Pointers
Post by: LarryMc on December 08, 2015, 09:37:48 PM
But you understand pointers better than you did and that was the whole point, right?
Title: Re: Pointers
Post by: Andy on December 09, 2015, 03:18:15 AM
Correct!

And I can see myself using pointers a great deal more.

The beauty for me is that you can set the size with a variable instead of a number, this allows for creating just enough "space" for something like an array, rather than waisting memory on a static size which might not be enough.

You can also (if the size becomes insufficient) copy the details to another, delete it and use the NEW command to set the new size. You can then copy the details back.

It's good stuff!

Thanks very much for the walkthrough.

Andy.

Title: Re: Pointers
Post by: billhsln on December 09, 2015, 10:29:10 AM
To everyone, this is a great bunch of examples and documentation on how pointers work.  I wanted to say thanks to all of you for all the work you all did on this.  I still may not totally understand pointers, but I think with all the explanations here, I might get a much better understanding.

So, thanks to everyone who responded to this.

Bill
Title: Re: Pointers
Post by: Andy on December 10, 2015, 02:28:49 AM
Bill,

That's very kind of you, but Larry must really take the credit, all I did was scratch my head a few times and tried to follow what Larry was telling me or hinting at.

I am thinking of writting a few little example programs which I can bunch together to help anyone who wants to understand pointers (at least some of the basics).

I would of course run it past "a bigger brain" than mine first!

Thanks,
Andy.
Title: Re: Pointers
Post by: aurelCB on December 11, 2015, 02:56:30 AM
If you have problem with space or unknown size  one of
options is Linked List (of pointers or UDT)
There is no problem if you use pointer as member of UDT if
you properly cast this pointer when is used.
So back to Linked List ....each member of linked list can be added by runtime
and because of automatic mangment of linked list size is not problem.