static
1、 关键字static的作用是什么?
在C语言中,关键字static有三个明显的作用:
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
2.static具体到修饰不同的变量函数对应的特点:
-
修饰局部变量
static修饰局部变量时,使得被修饰的变量成为静态变量,存储在静态区。存储在静态区的数据生命周期与程序相同,在main函数之前初始化,在程序退出时销毁。(无论是局部静态还是全局静态) -
修饰全局变量
全局变量本来就存储在静态区,因此static并不能改变其存储位置。但是,static限制了其链接属性。被static修饰的全局变量只能被该包含该定义的文件访问(即改变了作用域)。 -
修饰函数
static修饰函数使得函数只能在包含该函数定义的文件中被调用。对于静态函数,声明和定义需要放在同一个文件夹中。 -
修饰成员变量
用static修饰类的数据成员使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象,所有的对象都只维持同一个实例。 因此,static成员必须在类外进行初始化(初始化格式:int base::var=10;),而不能在构造函数内进行初始化,不过也可以用const修饰static数据成员在类内初始化。 -
修饰成员函数
用static修饰成员函数,使这个类只存在这一份函数,所有对象共享该函数,不含this指针,因而只能访问类的static成员变量。静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。例如可以封装某些算法,比如数学函数,如ln,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好。 -
最重要的特性:隐藏
当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏。
static修饰成员变量:同一个类的所有实例共享一个静态成员变量
#include<iostream>
using namespace std;
class S1
{
public:
static int a;
void say(){
cout << a << endl;
}
protected:
private:
};
int S1::a = 10;
void main(){
S1 s1;
S1 s2;
s1.a = 5;
s1.say();//5
s2.say();//5
s2.a = 6;
s1.say();//6
system("pause");
}
const
在C语言中const修饰一个全局变量,无论如何都无法修改变量的值
在C语言中如果const修饰一个局部变量,则只能通过指针变量来改变其值
const在最前面修饰得是指针变量的类型,不能通过指针变量修改对应的内容。
const在中间修饰的是指针变量,所指向的地址不能改变。
#include <stdio.h>
//在C语言construction修饰一个全局变量,无论如何都无法修改变量的值
const int a = 100;
void test1()
{
printf("a = %d\n", a);
//a = 200;
//printf("a = %d\n", a);
//int *p = &a;
//*p = 200;
//printf("a = %d\n", a);
}
void test2()
{
//在C语言中如果const修饰一个局部变量,则只能通过指针变量来改变其值
const int b = 200;
printf("b = %d\n", b);
//b = 666;
//printf("b = %d\n", b);
int *p = &b;
*p = 888;
printf("b = %d\n", b);
}
void test3()
{
int c = 100;
//int *p = &c;
//如果const修饰指针变量的类型,则不能通过指针变量修改保存的地址里面的内容
//const int *p = &c;
//如果const修饰指针变量,则不能修改指针变量保存的地址
//int *const p = &c;
//如果既修饰指针变量的类型又修饰指针变量,则只能通过原本的变量修改内容,无法通过指针变量修改
const int * const p = &c;
printf("*p = %d\n", *p);
//想要修改p指针里面保存的地址里面的内容,如何修改
//方法1:直接通过c变量修改
c = 666;
printf("*p = %d\n", *p);
//方法2:直接通过*p修改
*p = 777;
printf("*p = %d\n", *p);
//方法3:直接修改p保存的地址
int d = 888;
p = &d;
printf("*p = %d\n", *p);
}
int main(int argc, char *argv[])
{
test3();
return 0;
}
c++ 中
#include <iostream>
using namespace std;
//C++中的const使用方法与C语言基本类似
//对全局变量和指针变量修饰是一模一样的,但是对局部变量的操作有区别
void test1()
{
//const如果修饰一个局部变量,局部变量保存值
//操作系统会认为当前变量是不会被改变的,所以会将当前变量和值保存在符号常量表中
//保存在符号常量表中之后,下次使用当前变量时,不会从原本变量的地址中取值,而是
//从符号常量表中取值,所以即使改变原本的地址的内容,使用变量时发现值还是没改
//const int a = 100;
//使用volatile修饰变量,表示当前变量时易变的,所以不会保存在符号常量表中
const volatile int a = 100;
cout << "a = " << a << endl;
// a = 666;
// cout << "a = " << a << endl;
//C++对类型严格要求,需要保证左右值类型必须一样
int *p = (int *)&a;
*p = 666;
cout << "&a = " << &a << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "a = " << a << endl;
}
void test2()
{
int m = 100;
//如果const修饰的变量保存的是一个变量,则不会讲变量保存在符号常量表中
const int a = m;
int *p = (int *)&a;
*p = 666;
cout << "*p = " << *p << endl;
cout << "a = " << a << endl;
}
struct stu{
int a;
int b;
char c;
};
void test3()
{
//如果const修饰的变量的类型是构造数据类型,则也不会保存在符号常量表中
const stu s1 = {100, 200, 'w'};
stu *p = (stu *)&s1;
p->a = 666;
p->b = 777;
p->c = 'q';
cout << s1.a << " " << s1.b << " " << s1.c << endl;
}
int main(int argc, char *argv[])
{
test3();
return 0;
}
``
3 – 符号常量表 const int a = 10;符号常量表。
**/
const如果修饰一个局部变量,局部变量保存值.操作系统会认为当前变量是不会被改变的,所以会将当前变量和值保存在符号常量表中。
保存在符号常量表中之后,下次使用当前变量时,不会从原本变量的地址中取值,而是从符号常量表中取值,所以即使改变原本的地址的内容,使用变量时发现值还是没改。
改了没,他确实改了,但是你用的时候却还是改之前的那个狗子了。