C/C++中static关键字用法

静态变量的意思是:该变量在内存中的地址不变,并不是说它的值不变。
 - 静态变量和自动变量一样,具有块作用域、无链接,但是具有静态存储期,当程序离开它们所在的函数后,静态变量不会消失,
 - 不能在函数形参中使用static,如

int test(static int flu );//不允许

静态全局变量

在全局变量之前加上关键字static,该全局变量就被定义成了一个静态全局变量

特别注意:

1.静态全局变量在内存中的存储位置:静态区(全局区)。 [注]:静态区(全局区)在整个程序运行期间都存在

2.静态全局变量的初始化:未经初始化的静态全局变量会被程序自动初始化为0。 [注]:在C语言中,未经初始化的全局变量的值是任意的;而在C++中,未经初始化的全局变量也会被程序自动初始化为0

3.全局变量和静态全局变量的存储方式是一样的,但不同的是全局变量在整个源代码中都是可以使用的,而静态全局变量只能在当前文件中使用

比如一个程序有3个文件a.cpp、b.cpp和c.cpp,如果在文件a.cpp中定义了一个全局变量x,那么变量x在文件a.cpp、b.cpp和c.cpp中都可以使用;但如果在文件a.cpp中定义了一个静态全局变量y,那么变量y只能在文件a.cpp中使用文件b.cpp和文件c.cpp都不可以使用该静态全局变量y

源文件file1.cpp:

int aaa = 666;
static int bbb = 999;

 源文件file2.cpp:

// 文件file2.cpp
extern int aaa; //成功:期望使用文件file1中定义的全局变量aaa
extern int bbb; //错误:期望使用文件file1中定义的静态全局变量bbb,但bbb是static类型,只能在file1中使用,无法被其他文件使用

使用静态全局变量的好处:

  1. 将一个全局变量定义为静态全局变量,相当于让该全局变量对该程序的其他源文件进行了“隐藏”,也就是说该静态全局变量只能在定义它的源文件中使用,而程序的其他源文件则无法访问该变量
  2. 程序中的其他源文件中可以使用与该静态全局变量同名的变量,而不会发生冲突.

在C/C++程序中,如果一个全局变量仅仅在单个源文件中使用,则可以将该全局变量修改为静态全局变量,以降低模块间的耦合度.

使用局部静态变量

在局部变量之前加上关键字static,该局部变量就被定义成了一个静态局部变量

特别注意:

  1. 静态局部变量在内存中的存储位置:静态区(全局区)。[注]:普通局部变量在内存中的存储位置为栈区
  2. 静态局部变量的初始化:未经初始化的静态局部变量会被程序自动初始化为0。[注]:在C/C++中,未经初始化的普通局部变量值是任意的
  3. static并没有改变局部变量的作用域。换句话说就是静态局部变量的作用域仍是局部作用域,当定义它的函数或语句块结束的时候,其作用域也就随之结束。 [注]:与之相反,static改变了全局变量的作用域(在声明它的文件之外是不可见的)
  4. static虽然没有改变局部变量的作用域,但它改变了局部变量在内存中的存储位置(而static修饰的全局变量在内存中的存储位置则没有被static改变),即从原来的栈区中存放改变为静态区(全局区)中存放。因此静态局部变量在离开其作用域时,并没有像一般局部变量那样被销毁,而是仍驻留在内存中的静态区(全局区)中,直到程序结束,只不过在其离开自己的作用域时,我们无法再对其进行访问
  5. 在C/C++中,如果全局变量仅有单个函数访问,则可以将该全局变量改为该函数的静态局部变量,以降低模块间的耦合度
//使用局部静态变量
#include<stdio.h>
void trystat(void);

int main(void){
    int count ;
    for (count = 1; count < 5; count++){
        printf("Here comes iteration %d:\n",count);
        trystat();
    }
    
    return 0;
} 

void trystat(void){
    int fade = 1;
    static int stay1 ;
    static int stay2 = 1 ;
    printf("fade = %d    stay1 = %d     stay2 = %d\n", fade++, stay1++, stay2++);
}
/*
结果: 
    Here comes iteration 1:
    fade = 1    stay1 = 0     stay2 = 1
    Here comes iteration 2:
    fade = 1    stay1 = 1     stay2 = 2
    Here comes iteration 3:
    fade = 1    stay1 = 2     stay2 = 3
    Here comes iteration 4:
    fade = 1    stay1 = 3     stay2 = 4


分析:
每次调用trystat()都会初始化fade,但是stay2只在编译trystat()是被初始化一次,
如果为显式初始化静态变量,如stay1,它会被默认初始化为0 

静态函数

在函数的返回值类型前加上关键字static,该函数就被定义成了一个静态函数

特别注意:和静态全局变量相似,静态函数只能在声明它的源文件中可见,而不能被该程序的其他源文件所使用。

使用静态函数的好处:

  1. 在该程序的其他源文件中可以定义和使用与该静态函数同名的函数,而不会发生冲突
  2. 将一个普通函数定义为函数,相当于让该函数对该程序的其他源文件进行了“隐藏”,也就是说该静态函数只能在定义它的源文件中使用,而程序的其他源文件则无法调用该函数
  3. 静态函数会被自动分配在一个一直使用的存储区域,直到程序结束。这样避免了普通函数在调用时的进栈出栈操作,从而提高程序的运行速度

源文件file1.cpp:

//文件file1.cpp

extern void fun1(){......} //定义函数fun1
static void fun2(){......} //定义静态函数fun2

源文件file2.cpp:

//文件file2.cpp

extern void fun1();//成功:期望使用文件file1.cpp中的函数fun1
extern void fun2();//错误:期望使用文件file1.cpp中的静态函数fun2,但fun2是static类型函数,只能在file1中使用,无法被其他文件使用 

总结:static在C语言中的作用

  1. 隐藏功能:static修饰的全局变量和普通函数只能在定义它们的源文件中使用,相当于对程序中的其他源文件进行了隐藏
  2. 默认初始化功能:static修饰的变量,不管是全局变量还是局部变量,在用户没有显式初始化它们的条件下,系统都会将他们默认初始化为0
  3. 延长生命周期功能:static修饰的局部变量存储在内存的静态区(全局区)而非栈区,而静态区中存储的内容只会在程序结束时被OS释放,因此当static修饰的局部变量离开自己的作用域时,其不会像一般局部变量那样被系统销毁,而是一直驻留在系统的内存中,直到程序结束。

静态类成员变量

自定义类中被static修饰的成员变量

特别注意:

1.静态数据成员在内存中的存储位置:静态区(全局区)

2.使用:

语法:类名::静态数据成员名

 3.静态数据成员属于类换句话说就是类的静态数据成员为其所有对象所共享,不管该类有多少对象,静态数据成员只有一份存储于公共的内存中
特点:无论创建了多少个对象,程序都只创建一个静态类变量副本。也就是说类的所有对象共享同一个静态成员。
静态数据成员注意事项:

  • - 在类中声明
  • - 在包含类方法的文件中初始化
  • - 初始化时使用作用域运算符来指出静态成员所属的类
  • - 如果静态成员是const整数类型或枚举类型,则可以在类声明中初始化
class Test
{
public:
    Test();
    static int nums;
};
Test::Test()
{
    cout<<nums++<<endl;
}
int Test::nums = 0;
int main(int argc, char *argv[])
{
    Test aa,bb,cb;
    return 0;
}
结果为:
0
1
2


静态类成员函数

自定义类中被static修饰的成员函数

 特别注意

1.在C++的自定义类中,一个常规的成员函数声明往往意味着:

  • 该成员函数能够访问其所在类的私有部分

  • 该成员函数位于其所在类的作用域之中

  • 该成员函数必须由一个对象去激活从而被调用(通过this指针来实现)

如果将该类的一个成员函数声明为static,则可以只让它拥有前两种性质

2.使用:

语法1:类名::静态成员函数名
语法2:对象名.静态成员函数名

3.和静态数据成员一样,静态成员函数也属于类,类的静态成员函数为其所有对象所共享。

4.类中的普通成员函数既可以访问一般成员变量,也可以访问静态数据成员;而类中的静态成员函数只能访问类中的静态数据成员

[解释]:编译器在编译程序中的自定义类时,会在类中的每个普通成员函数中插入this指针,而对static修饰的静态成员函数则不会插入this指针。由于静态成员函数中没有this指针,因此静态成员函数无法在其函数体内访问非静态数据成员;相反,由于静态数据成员属于类而非特定对象,故不需要this指针也可以在函数体内访问静态数据成员,因此不管是普通成员函数还是静态成员函数,都可以在其函数体内访问静态数据成员。

5.同理,普通成员函数中可以调用静态成员方法,而静态成员方法中不能调用普通成员函数

可以将成员函数声明为静态的(函数声明必须包含关键字static,但如果函数定义是独立的,则其中不能包含static关键字)
注意事项:

  • - 不能通过对象来调用静态函数,实际上静态成员函数甚至不能使用this指针,如果静态成员函数是在公有部分声明的,则可以使用类名和作用域解析运算符来调用它
  • - 静态成员不与特定的对象关联,**因此只能使用静态数据成员**,不能使用非静态数据成员,因为它们可能还没初始化。
class Test
{
public:
    Test();
   //类中声明
   static int print(){ cout<<"hello";}
};
int Test::nums = 0;
int main(int argc, char *argv[])
{
    Test::print();
    return 0;
}


 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值