标题：静态static
C++中的static
简介C++的static有两种用法：面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数，不涉及类；后者主要说明static在类中的作用。面向过程设计中的static1、静态全局变量 

C中的static函数
分类static 函数内部函数和外部函数
当一个源程序由多个源文件组成时，C语言根据函数能否被其它源文件中的函数调用，将函数分为内部函数和外部函数。内部函数（又称静态函数）
如果在一个源文件中定义的函数，只能被本文件中的函数调用，而不能被同一程序其它文件中的函数调用，这种函数称为内部函数。
定义一个内部函数，只需在函数类型前再加一个“static”关键字即可，如下所示：
static 函数类型 函数名(函数参数表)
{……}
关键字“static”，译成中文就是“静态的”，所以内部函数又称静态函数。但此处“static”的含义不是指存储方式，而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是：不同的人编写不同的函数时，不用担心自己定义的函数，是否会与其它文件中的函数同名，因为同名也没有关系。外部函数外部函数的定义：在定义函数时，如果没有加关键字“static”，或冠以关键字“extern”，表示此函数是外部函数：
[extern] 函数类型 函数名(函数参数表)
{……}
调用外部函数时，需要对其进行说明：
[extern] 函数类型 函数名(参数类型表)[，函数名2(参数类型表2)……]；
[案例]外部函数应用。
（1）文件mainf.c
main()
{ extern void input(…),process(…),output(…);
input(…); process(…); output(…);
}
（2）文件subf1.c
……
extern void input(……) /*定义外部函数*/
{……}
（3）文件subf2.c
……
extern void process(……) /*定义外部 函数*/
{……}
（4）文件subf3.c
……
extern void output(……) /*定义外部函数*/
{……}
vb中的static语句
语句在过程级别中使用，用于声明变量并分配存储空间。在整个代码运行期间都能保留使用 Static 语句声明的变量的值。
static语句声明的变量，与dim语句声明的变量的主要区别是：前者只能在sub或function过程中使用，在退出sub或function过程后变量的值保留；后者使用在sub或function过程中时，退出sub或function过程后变量的值不保留。语法Static varname[([subscripts])] [As [New] type] [, varname[([subscripts])] [As [New] type]] . . .
Static 语句的语法包含下面部分：部分 描述varname 必需的。变量的名称；遵循标准变量命名约定。 
subscripts 可选的。数组变量的维数；最多可以定义 60 维的多维数组。subscripts 参数使用下面的语法： 
[lower To] upper [,[lower To] upper] . . . 
如果不显式指定 lower，则数组的下界由 Option Base 语句控制。如果没有 Option Base 语句则下界为 0。 
New 可选的。用它可以隐式地创建对象的关键字。如果使用 New 声明对象变量，则在第一次引用该变量时将新建该对象的实例，因此不必使用 Set 语句来对该对象引用赋值。New 关键字不能用来声明任何内部数据类型的变量，也不能用来声明从属对象的实例。 
type 可选的。变量的数据类型；可以是 Byte、Boolean、Integer、Long、Currency、Single、Double、Decimal（目前尚不支持）、Date、String（对变长的字符串）、String * length（对定长的字符串）、Object、Variant、用户定义类型或对象类型。所声明的每个变量都要有一个单独的 As type 子句。说明模块的代码开始运行后，使用 Static 语句声明的变量会一直保持其值，直至该模块复位或重新启动。可以在非静态的过程中使用 Static 语句显式声明只在该过程内可见，但具有与包含该过程定义的模块相同生命期的变量。
可以在过程中使用 Static 语句来声明在过程调用之间仍能保持其值的变量的数据类型。例如，下面的语句声明了一个定长的整型数组：
Static EmployeeNumber(200) As Integer
下面的语句为 worksheet 的新实例声明了一个变量：
Static X As New Worksheet
如果在定义对象变量时没有使用 New 关键字，则在使用该变量之前，必须使用 Set 语句将一个已有的对象赋给这个引用对象的变量。在被赋值之前，所声明的这个对象变量有一个特定值 Nothing，这个值表示该变量没有指向任何对象的实例。若在声明中使用了 New 关键字，则在第一次引用对象时将新建一个该对象的实例。
如果不指定数据类型或对象类型，且在模块中没有使用 Deftype 语句，则按缺省情况，定义该变量为 Variant 类型。注意Static 语句与 Static 关键字很相似，但是针对不同的效果来使用的。如果使用 Static 关键字（如 Static Sub CountSales ()）来声明一个过程，则该过程中的所有局部变量的存储空间都只分配一次，且这些变量的值在整个程序运行期间都存在。对非静态过程而言，该过程每次被调用时都要为其变量分配存储空间，当该过程结束时都要释放其变量的存储空间。Static 语句则用来在非静态的过程中声明特定的变量，以使其在程序运行期间能保持其值。
在初始化变量时，数值变量被初始化为 0，变长的字符串被初始化为一个零长度的字符串 ("")，而定长的字符串则用 0 填充。Variant 变量被初始化为 Empty。用户自定义类型的变量的每个元素作为各自独立的变量进行初始化。
注意 如果在过程中使用 Static 语句，应和其它的声明语句（如 Dim）一样将其放在过程的开始。
JAVA中的static
作用有时你希望定义一个类成员，使它的使用完全独立于该类的任何对象。通常情况下，类成员必须通过它的类的对象访问，但是可以创建这样一个成员，它能够被它自己使用，而不必引用特定的实例。在成员的声明前面加上关键字static(静态的)就能创建这样的成员。如果一个成员被声明为static，它就能够在它的类的任何对象创建之前被访问，而不必引用任何对象。你可以将方法和变量都声明为static。static 成员的最常见的例子是main( ) 。因为在程序开始执行时必须调用main() ，所以它被声明为static。 
声明为static的变量实质上就是全局变量。当声明一个对象时，并不产生static变量的拷贝，而是该类所有的实例变量共同拥有一个static变量。声明为static的方法有以下几条限制： 
· 
它们仅能调用其他的static 方法。 
· 
它们只能访问static数据。 
· 
它们不能以任何方式引用this 或super（关键字super 与继承有关）。举例如果你需要通过计算来初始化你的static变量，你可以声明一个static块，Static 块仅在该类被加载时执行一次。下面的例子显示的类有一个static方法，一些static变量，以及一个static 初始化块： 
// Demonstrate static variables，methods，and blocks. 
class UseStatic { 
static int a = 3; 
static int b; 
static void meth(int x) { 
System.out.println("x = " + x); 
System.out.println("a = " + a); 
System.out.println("b = " + b); 
} 
static { 
System.out.println("Static block initialized."); 
b = a * 4; 
} 
public static void main(String args[]) { 
meth(42); 
} 
} 
一旦UseStatic 类被装载，所有的static语句被运行。首先，a被设置为3，接着static 块执行(打印一条消息)，最后，b被初始化为a*4 或12。然后调用main()，main() 调用meth() ，把值42传递给x。3个println ( ) 语句引用两个static变量a和b，以及局部变量x 。 
注意：在一个static 方法中引用任何实例变量都是非法的。 
下面是该程序的输出： 
Static block initialized. 
x = 42 
a = 3 
b = 12
C#中的static
使用 static修饰符声明属于类型本身而不是属于特定对象的静态成员。static修饰符可用于类、字段、方法、属性、运算符、事件和构造函数，但不能用于索引器、析构函数或类以外的类型。例如，下面的类声明为 static，并且只包含 static方法。
例如：
static class CompanyEmployee
{
public static string GetCompanyName(string name) { ... }
public static string GetCompanyAddress(string address) { ... }
}
一般来说，类中标注了static的函数与变量能在类外直接引用，比如说：
String  M_string1 =CompanyEmployee.GetCompanyName(M_string2)
而没有标注static的函数则必须声明一个类的实体，，有实体来引用。比如说：
static class CompanyEmployee          
{
public  string GetCompanyName(string name) { ... }     //没有Static
public static string GetCompanyAddress(string address) { ... }
}
CompanyEmployee M_CompE = new CompanyEmployee()
String M_string1 =M_CompE.GetCompanyName(M_string2)
函数调用
函数调用的一般形式
在程序中是通过对函数的调用来执行函数体的，其过程与其它语言的子程序调用相似。 
C语言中，函数调用的一般形式为： 
函数名(实际参数表) 
对无参函数调用时则无实际参数表。实际参数表中的参数可以是常数，变量或其它构造类型数据及表达式。各实参之间用逗号分隔。
java中的静态函数也叫做静态方法，通常调用方式如下：
类名.方法名(实际参数列表)
函数调用的方式
在C语言中，可以用以下几种方式调用函数： 
1. 函数表达式：函数作为表达式中的一项出现在表达式中，以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如：z=max(x,y)是一个赋值表达式，把max的返回值赋予变量z。 
2. 函数语句：函数调用的一般形式加上分号即构成函数语句。例如： printf ("%d",a);scanf ("%d",&b);都是以函数语句的方式调用函数。 
3. 函数实参：函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送，因此要求该函数必须是有返回值的。例如： printf("%d",max(x,y)); 即是把max调用的返回值又作为printf函数的实参来使用的。在函数调用中还应该注意的一个问题是求值顺序的问题。所谓求值顺序是指对实参表中各量是自左至右使用呢，还是自右至左使用。对此，各系统的规定不一定相同。介绍printf 函数时已提到过，这里从函数调用的角度再强调一下。 
【例】 
main() 
{ 
int i=8; 
printf("%d\n%d\n%d\n%d\n",++i,--i,i++,i--); 
} 
如按照从右至左的顺序求值。运行结果应为： 
8 
7 
7 
8 
如对printf语句中的++i，--i，i++，i--从左至右求值，结果应为： 
9 
8 
8 
9 
应特别注意的是，无论是从左至右求值， 还是自右至左求值，其输出顺序都是不变的， 即输出顺序总是和实参表中实参的顺序相同。由于Turbo C现定是自右至左求值，所以结果为8，7，7，8。上述问题如还不理解，上机一试就明白了。
被调用函数的声明和函数原型
在主调函数中调用某函数之前应对该被调函数进行说明（声明），这与使用变量之前要先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型，以便在主调函数中按此种类型对返回值作相应的处理。 
其一般形式为： 
类型说明符 被调函数名(类型 形参，类型 形参…)； 
或为： 
类型说明符 被调函数名(类型，类型…)； 
括号内给出了形参的类型和形参名，或只给出形参类型。这便于编译系统进行检错，以防止可能出现的错误。 
例 main函数中对max函数的说明为： 
int max(int a,int b); 
或写为: 
int max(int,int)； 
C语言中又规定在以下几种情况时可以省去主调函数中对被调函数的函数说明。 
1) 如果被调函数的返回值是整型或字符型时，可以不对被调函数作说明，而直接调用。这时系统将自动对被调函数返回值按整型处理。例8.2的主函数中未对函数s作说明而直接调用即属此种情形。 
2) 当被调函数的函数定义出现在主调函数之前时，在主调函数中也可以不对被调函数再作说明而直接调用。例如例8.1中，函数max的定义放在main 函数之前，因此可在main函数中省去对max函数的函数说明int max(int a,int b)。 
3) 如在所有函数定义之前，在函数外预先说明了各个函数的类型，则在以后的各主调函数中，可不再对被调函数作说明。例如： 
char str(int a); 
float f(float b); 
main() 
{ 
…… 
} 
char str(int a) 
{ 
…… 
} 
float f(float b) 
{ 
…… 
} 
其中第一，二行对str函数和f函数预先作了说明。因此在以后各函数中无须对str和f函数再作说明就可直接调用。 
4) 对库函数的调用不需要再作说明，但必须把该函数的头文件用include命令包含在源文件前部。
函数的嵌套调用
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的，不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。其关系可表示如图。 
图表示了两层嵌套的情形。其执行过程是：执行main函数中调用a函数的语句时，即转去执行a函数，在a函数中调用b 函数时，又转去执行b函数，b函数执行完毕返回a函数的断点继续执行，a函数执行完毕返回main函数的断点继续执行。 
【例】计算s=22!+32! 
本题可编写两个函数，一个是用来计算平方值的函数f1，另一个是用来计算阶乘值的函数f2。主函数先调f1计算出平方值，再在f1中以平方值为实参，调用 f2计算其阶乘值，然后返回f1，再返回主函数，在循环程序中计算累加和。 
long f1(int p) 
{ 
int k; 
long r; 
long f2(int); 
k=p*p; 
r=f2(k); 
return r; 
} 
long f2(int q) 
{ 
long c=1; 
int i; 
for(i=1;i<=q;i++) 
c=c*i; 
return c; 
} 
main() 
{ 
int i; 
long s=0; 
for (i=2;i<=3;i++) 
s=s+f1(i); 
printf("\ns=%ld\n",s); 
} 
在程序中，函数f1和f2均为长整型，都在主函数之前定义，故不必再在主函数中对f1和f2加以说明。在主程序中，执行循环程序依次把i值作为实参调用函数f1求i2值。在f1中又发生对函数f2的调用，这时是把i2的值作为实参去调f2，在f2 中完成求i2!的计算。f2执行完毕把C值(即i2!)返回给f1，再由f1返回主函数实现累加。至此，由函数的嵌套调用实现了题目的要求。由于数值很大，所以函数和一些变量的类型都说明为长整型，否则会造成计算错误。