Is there a way to get the address of a global variable? My aim is to make a routine that takes arguments by reference.
If it’s not possible, no problem, I’ll use an object and the
.& operator (or an array).
A simple example of what I want to do, in case someone can find a better way:
with score 0
[ Assign addr new_val;
addr-->0 = new_val;
[ Main ;
print MyGlobals.score, "^^"; ! Prints "0".
print MyGlobals.score, "^^"; ! Prints "42".
Yes, but it’s clunky.
The special symbol
#g$foovar is the position of global
foovar in the globals array. The address of the globals array is
#globals_array. So, in theory, you can do this:
Global foovar = 6;
Global barvar = 9;
! This is equivalent to: foovar = barvar;
(#globals_array-->#g$foovar) = (#globals_array-->#g$barvar);
The address of
foovar is therefore
#globals_array + WORDSIZE * #g$foovar.
The hitch is that in Z-code with -S, this throws a runtime error. The veneer (wrongly) thinks that
#globals_array is outside of writable memory. You can do this instead:
val = (#globals_array-->#g$barvar);
@storew #globals_array #g$foovar val;
I guess it’s possible that this is not spec-compliant? Maybe an interpreter could keep all its global variables in a cache and only write them out to
#globals_array when saving? I’m not sure whether that’s a possibility.
In Glulx, none of this is a problem. But I still wouldn’t build an API that required the caller to pass
#globals_array + WORDSIZE * #g$foovar as an argument. I mean, yuck.
Thanks for the detailed explanation!
While I agree it isn’t pretty, the API would only say “give me an address, and I’ll do something with the value it points to”. If an author doesn’t want to use the clunky global syntax, they can still use an object or an array. Also, I think it’s acceptable for an internal, non-public API.
(Also, it’s still possible to define a routine that, given a
#g$myglobal, will return it’s address. Still no pretty, but less ugly.)