在生活中,有些值是不发生变化的。比如一个人的身份证号码,血型,性别等等。
在计算机中要描述这些信息就需要有一个不变的量来表示。这种值我们就叫做常量。
在C语言中
1、常量的分类:
- 字面常量
1,3.14.‘q’,‘\n’,
- const定义的常量
当const 修饰一个标识符的时候,这个标识符依然是一个变量,但是它具有常属性,不能被直接改变。
例如:
#include<stdio.h>
int main()
{
int a = 10;
const int b = 10;
a = 20;
b = 20; //b为const修饰的变量,为不可修改的变量
return 0;
}
- #define定义的标识符常量
#include<stdio.h>
#define SZ 10 //SZ为标识常量
int main()
{
//int arr[需要一个常量];
int arr[10];//ok
int arr2[SZ];//在预编译的时候进行宏替换,将SZ替换成10
return 0;
}
- 枚举常量
枚举关键字:enum
#include<stdio.h>
enum week{
monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
int main()
{
printf("%d\n", monday ); 0
printf("%d\n", Tuesday ); 1
printf("%d\n", Wednesday); 2
printf("%d\n", Thursday); 3
printf("%d\n", Friday); 4
printf("%d\n", Saturday); 5
printf("%d\n", Sunday); 6
system("pause");
return 0;
}
而那些值可以随意改变的就叫做变量。
2、static修饰
static表示“静态”或者“全局”的意思,用来修饰变量和函数。经static修饰过后的变量或者函数的作用域或者存储域会发生变化,而由static修饰的变量在初始值方面也会表现出static关键字的优势。
- 全局静态变量
在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。
1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在);
2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化);
3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾;
定义全局静态变量的好处:
<1>不会被其他文件所访问和修改;
<2>其他文件中可以使用相同名字的变量,不会发生冲突;
- 局部静态变量
在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
1)内存中的位置:静态存储区;
2)初始化:未经初始化的局部静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。
注意:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。
当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。
- 静态函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件中可见,不能被其他文件所用。
定义静态函数的好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突 ;
<2> 静态函数不能被其他文件所用;
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。extern修饰的函数和变量具有外部链接属性。
在C++中
1、const修饰类成员
- const使用场景:
(1)const修饰形参,一般和引用同时使用;
(2)const修饰返回值;
(3)const修饰类数据成员,必须在构造函数的初始化列表中初始化;
(4)const修饰类成员函数,实际修饰隐含的this,表示在类中不可以对类的任何成员进行修改;
(5)在const修饰的成员函数中要对类的某个数据成员进行修改,该数据成员定义声明时必须加mutable关键字;(注释:mutalbe的中文意思是“可变的,易变的”,mutable 是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。)
(6)const不能修饰析构函数、赋值;
- (非)const对象和(非)const成员函数相互间的调用关系
1)const对象可以不可以调用非const成员函数,但可以调用const成员函数;
2)非const对象可以调用非const成员函数,也可以调用const成员函数;
3) const成员函数内可以调用其它的const成员函数,但不可以调用非const成员函数;
4) 非const成员函数内可以调用其它的const成员函数,也可以调用非const成员函数;
2、const修饰指针
- const int *a
- int *const a
这里const修饰的是 a ,a代表的是一个指针地址,因此不能赋给a其他的地址值,但可以修改a指向的值;
- const int * const a
这个代表a所指向的对象的值以及它的地址本身都不能被改变,也就是a所指向的对象及对象的值均不可改变;
- const对象的地址及const指针的关系
1) const 对象的地址只能赋值给指向const 对象的指针;
2) 指向const 对象的指针可以 被赋 以 一个非const 对象的地址 ;
3) 指向const 得指针常被用作函数的形式参数,保证被传递给函数的实际对象在函数得实际对象在函数中不会被修改;
4) 常量在定义后就不能被修改,所以它必须被初始化。未初始化的常量定义将导致编译错误(上面都是在说明const得问题,所以没有赋值,实际语句中要赋值的);3、static成员
声明为static的类成员(成员数据或成员函数)称为类的静态成员。
特性:
- 静态成员为所有类对象所共享,不属于某个具体的实例;
- 类静态成员即可用 (类名::静态成员) 或者 (对象.静态成员) 来访问;
- 类静态成员变量必须在类外定义,定义时不添加static关键字;
- 类的静态成员函数没有默认的this指针,因此在它里面不能使用任何非静态成员;
- 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值,const修饰符等参数;
注意:静态成员不计算在类的大小中,但能通过对象访问;普通对象能被普通成员函数调用,但不能对静态成员函数调用;非静态成员函数不可以调用静态成员函数;静态成员函数可以调用非静态成员函数;