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.