Consider a simple program that includes
main()
and another user-defined function:
#include "oxstd.h"
f(x) {
decl z;
}
main() {
decl y;
}
The section on function arguments already discussed the fact that there are three
things created by this program: the variable
y
inside
main()
, the variable
z
inside
f()
, and the formal argument
x
. Because
y
and
z
are declared inside curly brackets,
{ … }
, they only
exist
and only available to code inside those brackets. One way to say that is that
y
is a
local variable of
main()
. The Ox documentation says this:
Variables declared at the start of a statement block have scope and life restricted to the block. These variables are called automatic: they are created and initialized whenever the block is entered, and removed as soon as the block is exited.
So Ox uses the term
automatic not
local.
And, as we have already seen, the formal argument
x
can also only be accessed inside the function
f(x)
. Now consider this program:
#include "oxstd.h"
decl v;
f(x) {
decl z = x+v;
println("z = ",z);
v = 4;
}
main() {
decl y;
v = 3;
f(2);
println("v = ",v);
}
Here the variable
v
is defined outside of any brackets. That makes
v
a
global variable. It is visible anywhere in the file, including inside curly brackets. Ox uses this description:
Variables declared outside any statement block have global scope and life; these are called static.
Ox would call
v
static because it
exists
at the start of the program (at RT0) and continues to exist until the program ends. So its existence is static, whereas
z
is not static. It is created and destroyed
automatically each time
f()
is called and finishes.
One good reason to use global variables in your program is to make information available to functions that (for various reasons) are not passed through arguments. But this can be
dangerous once a program becomes complicated. The reason is that any part of the program can change the value of a global variable, so one function may affect the information available to another function.
So what happens when one function is called depends on if another function has been called before it or not. This kind of implicity interdependence makes it very hard to know if a program is correct or not. You can see it above in the simple program. What value of
v
has in
main()
when it is printed depends on whether
f()
has been called or not. Move the location of the call to
f()
and the other output changes.
One way to use global variables to share information safely is to declare them constant:
#include "oxstd.h"
const decl v = 3;
f(x) {
decl z = x + v;
println("z = ",z);
}
main() {
decl y;
f(2);
println("v = ",v);
}
In this version of the program
v
is a global constant equal to 3. The value of a global constant must be set when it is declared because this value is fixed before the program starts to run. Then Ox will check the syntax of the code and ensure that no statement that could change the value of
v
will be allowed. Now
f()
and
main()
can share the value of
v
knowing the value is set only once and cannot be changed.
Note a few things about this. First,
const decl
cannot appear inside the definition of a function:
f(x) {
const decl v = 5;
…
}
Some languages might allow "local constants" like this, but not Ox. (In Ox a
class
can have internal constants that can only be set by the constructor of the class.)
Constants can be set to values based on simple expressions, but they can't rely on Ox functions because these get called during execution and global constants are set before execution.
const decl
x = 5+6,
y = < 5, 6, 7 >,
z = exp(2.0);