在C语言中
- 1.static全局变量:
static全局变量:其中.text段保存进程所执行的程序二进制文件,.data段保存进程所有的已初始化的全局变量,.bss段保存进程未初始化的全局变量(其他段中还有很多乱七八糟的段,暂且不表)。在进程的整个生命周期中,.data段和.bss段内的数据时跟整个进程同生共死的,也就是在进程结束之后这些数据才会寿终就寝。
当一个进程的全局变量被声明为static之后,它的中文名叫静态全局变量。静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源文件内有效,其他源文件无法访问它。所以,普通全局变量穿上static外衣后,它就变成了新娘,已心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。
#include "file1.h"
static char* h = "hello!";
void printStr()
{
printf("%s\n", hello);
}
//file2.c是主程序所在文件,file2.c中如果引用hello会编译出错
#include "file1.h"
int main()
{
printStr();
printf("%s\n", h); //此处无法用引用file1.c中的h
return 0;
}
- 2.static局部变量:
普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态分配,但是记得使用完这个堆空间后要释放之。
static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有如下几个区别:
1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss段内,原因见3)),所以它虽然是局部的,但是在程序的整个生命周期中存在。
2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是说虽然它会在程序的整个生命周期中存在,由于它是static的,它不能被其他的函数和源文件访问。
3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为0,以后每次调用静态局部变量的时候都用上次调用后的值。这个比较好理解,每次函数调用静态局部变量的时候都修改它然后离开,下次读的时候从全局存储区读出的静态局部变量就是上次修改后的值。
注意:由于static局部变量的这种特性,使得含静态局部变量的函数变得不可重入,即每次调用可能会产生不同的结果。这在多线程编程时可能会成为一种隐患。需要多加注意。
void printStr()
{
int normal = 0;
static int stat = 0; //this is a static local var
printf("normal = %d ---- stat = %d\n",normal, stat);
normal++;
stat++;
}
//为了便于比较,两个变量:普通局部变量normal和静态局部变量stat,它们都被赋予初值0;
int main()
{
printStr();
printStr();
printStr();
printStr();
printf("call stat in main: %d\n",stat);//此处不能用stat因为是另外一个函数的static局部变量,报错未定义标识符stat
return 0;
}
//输出0 0 | 0 1 | 0 2 | 0 3
- 3.static函数:
当程序中有很多个源文件的时候,肯定会让某个源文件只提供一些外界需要的接口,其他的函数可能是为了实现这些接口而编写,这些其他的函数你可能并不希望被外界(非本源文件)所看到,这时候就可以用static修饰这些“其他的函数”。
所以static函数的作用域是本源文件,可以把它想象为面向对象中的一个源文件中private函数就可以了。
//头文件中:
#include <stdio.h>
static int called();
void printStr();
#include "file1.h"
static int called()
{
return 6;
}
void printStr()
{
int returnVal;
returnVal = called(); //此处是可以调用called函数
printf("returnVal=%d\n",returnVal);
}
#include "file1.h"
int main()
{
int val;
val = called(); //此处识别不了called
printStr();
return 0;
}
以上内容借鉴https://www.cnblogs.com/JMatrix/p/8194009.html,在此感谢作者!
在C++中
总结一下static在类中修饰成员变量,和成员函数的作用:
- 1.修饰成员变量:
static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量
有以下特性:
1>.静态成员为所有类对象所共享,不属于某个具体的实例.意思是这个变量对于每个对象来说都是一个变量。是共同可以拥有的。
2>.静态成员变量必须在类外定义/初始化,定义时不添加static关键字。如果在类内定义,那么每创建一个对象,就将count的值给重新赋值修改了。那么他共享的意义就没有了
3>.类静态成员可用类名::静态成员(共享的是类的属性,不随对象)||对象.静态成员来访问
4>.静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值
5>.静态变量不在对象中,因而对象的大小不包含成员变量
应用:求Date总共创建了多少个有效对象?
class A1{
public:
A1()
{
count++;
}
A1(const A1 &x)
{
count++;
}
~A1(){
count--;
}
private:
int x;
public:
static int count;
};
int A1::count = 0; //静态成员变量是类的属性
void Test()
{
A1 x1;
A1 x2;
A1 x3(x1);
}
int main()
{
Test();
A1 x4;
A1 x5;
// 静态成员变量是所有类对象共享的成员变量,不属于某个具体的对象,以下输出结果一样
cout << x4.count << endl;
cout << x5.count << endl;
return 0;
}
class A1{
public:
A1()
{
}
A1(const A1 &x)
{
}
~A1(){
}
static int Getcount()
{
return count;
}
private:
int x;
static int count;
};
int main()
{
A1 x1;
cout << sizeof(x1) << endl; //-->4
system("pause");
return 0;
}
- 2.修饰成员函数:
用static修饰的成员函数,称之为静态成员函数。当要在其他函数里读取私有的静态成员,可用一个静态函数来读取
特性:
1>静态成员函数没有隐藏的this指针,不能访问任何非静态成员
2> 成员函数也不属于任何一个对象,访问也可以使用上面所述的两种方法来访问.
class A1{
public:
A1()
{
count++;
}
A1(const A1 &x)
{
count++;
}
~A1(){
count--;
}
static int Getcount()
{
return count;
}
private:
int x;
static int count;
};
int A1::count = 0;
void Test()
{
A1 x1;
A1 x2;
A1 x3(x1);
}
int main()
{
Test();
A1 x4;
A1 x5;
//cout << x4.count << endl;
//cout << A1::count << endl;//这个两个方法是无法访问的
cout << x5.Getcount() << endl;
cout << A1::Getcount() << endl;//这两个方法是可以访问的
return 0;
}
通过对比,可有以下可得结论
- 静态成员函数不可以调用非静态成员函数 原因很简单,上面说静态成员函数中不会传this指针,而非静态成员函数是需要this指针传入的,因而在静态成员函数中调用非静态成员函数是无法给非静态成员函数传入this指针的
2.非静态成员函数可以调用类的静态成员函数 静态函数不需要this指针,非静态成员函数不影响静态的
https://www.runoob.com/w3cnote/cpp-static-usage.html