String constants (e.g., `fred'), lists (e.g., [1,2,3]) and typed lists (e.g., [1,2,3]:INT) are static data.
This means that the address of the (initialised) data is fixed when the program is run.
Normally you don't need to worry about this, but, for instance, if you want to have a series of lists as initialised arrays you might be tempted to use some kind of loop:
PROC main()
DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG
FOR i:=0 TO 9
a[i]:=[1, i, i*i]
/* This assignment is probably not what you want! */
ENDFOR
FOR i:=0 TO 9
p:=a[i]
WriteF('a[\d] is an array at address \d\n', i, p)
WriteF(' and the second element is \d\n', p[1])
ENDFOR
ENDPROC
The array a is an array of pointers to initialised arrays (which are all three elements long).
But, as the comment suggests and the program shows, this probably doesn't do what was intended, since the list is static.
That means the address of the list is fixed, so each element of a gets the same address (i.e., the same array).
Since i is used in the list, the contents of that part of memory varies slightly as the first FOR loop is processed.
But after this loop the contents remain fixed, and the second element of each of the ten arrays is always nine.
This is an example of the output that will be generated (the `...' represents a number of similar lines):
a[0] is an array at address 4021144 and the second element is 9 a[1] is an array at address 4021144 and the second element is 9 ... a[9] is an array at address 4021144 and the second element is 9
One solution is to use the dynamic typed-allocation operator NEW (see 14.4 NEW and END Operators).
Another solution is to use the function List and copy the normal list into the new E-list using ListCopy:
PROC main()
DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG
FOR i:=0 TO 9
a[i]:=List(3)
/* Must check that the allocation succeeded before copying */
IF a[i]<>NIL THEN ListCopy(a[i], [1, i, i*i], ALL)
ENDFOR
FOR i:=0 TO 9
p:=a[i]
IF p=NIL
WriteF('Could not allocate memory for a[\d]\n', i)
ELSE
WriteF('a[\d] is an array at address \d\n', i, p)
WriteF(' and the second element is \d\n', p[1])
ENDIF
ENDFOR
ENDPROC
The problem is not so bad with string constants, since the contents are fixed. However, if you alter the contents explicitly, you will need to take care not to run into the same problem, as this next example shows.
PROC main()
DEF i, strings[10]:ARRAY OF LONG, s:PTR TO CHAR
FOR i:=0 TO 9
strings[i]:='Hello World\n'
/* This assignment is probably not what you want! */
ENDFOR
s:=strings[4]
s[5]:="X"
FOR i:=0 TO 9
WriteF('strings[\d] is ', i)
WriteF(strings[i])
ENDFOR
ENDPROC
This is an example of the output that will be generated (again, the `...' represents a number of similar lines)::
strings[0] is HelloXWorld strings[1] is HelloXWorld ... strings[9] is HelloXWorld
The solution, once more, is to use dynamic allocation.
The functions String and StrCopy should be used in the same way that List and ListCopy were used above.
Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.