Static qualifiers allocate the memory address of a variable in a higher enclosing level.
For a function body, the variable is allocated in the block where the function is defined; so in the code
struct s {
int count() {
static int c=0;
++c;
return c;
}
}
there is one instance of the variable c for each
object s (as opposed to each call of count).
Similarly, in
int factorial(int n) {
int helper(int k) {
static int x=1;
x *= k;
return k == 1 ? x : helper(k-1);
}
return helper(n);
}
there is one instance of x for every call to
factorial (and not for every call to helper), so this is
a correct, but ugly, implementation of factorial.
Similarly, a static variable declared within a structure is allocated in the block where the structure is defined. Thus,
struct A {
struct B {
static pair z;
}
}
creates one object z for each object of type A created.
In this example,
int pow(int n, int k) {
struct A {
static int x=1;
void helper() {
x *= n;
}
}
for(int i=0; i < k; ++i) {
A a;
a.helper();
}
return A.x;
}
there is one instance of x for each call to pow, so this
is an ugly implementation of exponentiation.
Loop constructs allocate a new frame in every iteration. This is so that higher-order functions can refer to variables of a specific iteration of a loop:
void f();
for(int i=0; i < 10; ++i) {
int x=i;
if(x==5) {
f=new void() {write(x);};
}
}
f();
Here, every iteration of the loop has its own variable x, so f()
will write 5. If a variable in a loop is declared static, it will be
allocated where the enclosing function or structure was defined (just as if it
were declared static outside of the loop). For instance, in:
void f() {
static int x;
for(int i=0; i < 10; ++i) {
static int y;
}
}
both x and y will be allocated in the same place, which is
also where f is allocated.
Statements may also be declared static, in which case they are run at the place where the enclosing function or structure is defined. Declarations or statements not enclosed in a function or structure definition are already at the top level, so static modifiers are meaningless. A warning is given in such a case.
Since structures can have static fields, it is not always clear for a qualified name whether the qualifier is a variable or a type. For instance, in:
struct A {
static int x;
}
pair A;
int y=A.x;
does the A in A.x refer to the structure or to the pair variable.
It is the convention in Asymptote that, if there is a non-function variable with
the same name as the qualifier, the qualifier refers to that variable, and not
to the type. This is regardless of what fields the variable actually possesses.