Statement STATIC Foundation

Declaration and initialization of STATIC variables.

Syntax
STATIC <VarName> [[:= <Expression>], ... ]
Parameters
<VarName>
<VarName> designates the name of a STATIC variable. If the array element operator [] immediately follows <VarName>, an array is assigned to the variable. The array can be dimensioned by specifying a number of elements, as in:
STATIC <aArray>[<nDimension1>, <nDimension2>,...] // or 
STATIC <aArray>[<nDimension1>][<nDimension2>]... 
If an array is declared in this form, all array elements have the value NIL. The size of an array is unlimited in the number of elements and the number of dimensions.
Attention: <VarName> must be specified at compile time and cannot be generated with the macro operator (&) at runtime.
<Expression>
<Expression> is an expression whose value can be assigned to the variable using the inline assignment operator (:=). If no assignment is done, the variable is initialized with the value NIL. If the variable was initialized as an array as described above, no assignment can be made. The value of the expression <Expression> must be known at compile time and can therefore only be a constant or a literal array. The expression may not contain a function call, since this can be evaluated only at runtime.
Multiple variables can be declared as long as the variable names, including assignment, are separated by commas.
Description

The STATIC declaration declares variables of storage class STATIC. The STATIC variables are initialized only once and their lifetime is the entire runtime. Their visibility is dependent on the declaration:

If STATIC variables are declared within a function or procedure, they are visible only within that function or procedure, and not in any subfunctions or procedures.

If STATIC variables are declared in the source code file before the first FUNCTION or PROCEDURE declaration, their visibility extends to all functions and procedures in that source code file. They are not visible to modules in other files. In order for STATIC variables to have file-wide visibility, you must use the /N compile switch.

STATIC variables keep their value after the function or procedure in which they are declared ends. They are not automatically released. After multiple calls to the function or procedure in which the STATIC variable is declared, the variable contains what was set as of the end of the last call. This also applies to recursive functions. STATIC variables are initialized only once and keep their value.

The STATIC declaration must come before all other executable statements, including the statements PRIVATE, PUBLIC and PARAMETERS. <VarName>can occur only once within a function. If a PRIVATE or PUBLIC variable already exists with the name <VarName>, it is "hidden" and is no longer visible within the function or procedure in which a STATIC variable of the same name is declared.

The length of a variable name is unlimited, but only the first 255 characters are significant. A variable name consists of alphanumeric characters, and the first character may not be numeric. The underscore (_) is permitted as a special character.

A STATIC variable can be initialized in the declaration, using the inline assignment operator (:=). STATIC variables can be initialized with constants or literal arrays of any dimension and size, and the value must be known at compile time. If no assignment is made, STATIC variables have the value NIL. The initialization values are assigned to the variables when the program starts.

STATIC variables cannot be saved in a file with the SAVE command. SAVE can only be used with PRIVATE and PUBLIC variables.

The macro operator (&) cannot compile an expression containing the name of a STATIC variable as a character string. The reason is that the references to STATIC variables are resolved during compilation and the symbol name does not exist at runtime.

The data type of STATIC variables can only be determined with the function Valtype() and not with the function Type(). This is because the Type() function uses the macro operator in order to determine the data type of a variable or expression. A character string must always be passed to the function Type(). Valtype() establishes the data type of a value without macros.

In order to be able to track STATIC variables in the debugger, the source code files (PRG files) must be compiled with the /B compiler switch so that the names of the STATIC variables remain available as debug information.

Examples
STATIC usage
// The example shows declaring and initializing STATIC variables 

STATIC aChar := { "A","B","C","D" }  // Variable visible 
                                     // throughout file 
PROCEDURE Main 
   STATIC cString := "Xbase++"       // Initialized STATICS 
   STATIC lLogic  := .T.             // only visible in procedure 
   STATIC aArray[4] , dDate, nNumber // Array with NIL elements 
                                     // and variables with value NIL 

   FOR nNumber:=1 TO 4 
       aArray[nNumber] := Test( nNumber ) 
   NEXT 

   ? aArray[1] == aChar[1]           // Result: .T. 

RETURN 


PROCEDURE Test( n ) 

RETURN aChar [n] 
UDF to generate temporary file names

// In the example, a UDF returns a different file name with each call, 
// which is suitable for generating temporary file names. 
// The file name is formed from a STATIC variable, a counter, and the 
// return value of the function. 

FUNCTION TempFileName() 
   STATIC snCount := 0 
   LOCAL  cFileName 

   IF ++ snCount == 100 
      snCount := 0 
   ENDIF 

   cFileName   := PadL( snCount, 2, "_" )    + ; 
                  StrTran( Time(), ":", "" ) + ; 
                  ".$$$" 
RETURN cFileName 
UDF for a random number generator
// In the example, a UDF generates random numbers from 0 to a maximum 
// positive number. 

FUNCTION Random( nLimit ) 
   STATIC snRandom 
   LOCAL nDecimals, cLimit 

   IF snRandom == NIL 
      snRandom := Seconds() / Exp(1) 
   ENDIF 

   snRandom    := Log( snRandom + Sqrt(2) ) * Exp(3) 
   snRandom    := Val( Str(snRandom - Int(snRandom), 17, 15 ) ) 
   cLimit      := Transform( nLimit, "@N" ) 
   nDecimals   := At(".", cLimit) 

   IF nDecimals > 0 
      nDecimals:= Len(cLimit)-nDecimals 
   ENDIF 

RETURN Round( nLimit * snRandom, nDecimals ) 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.