一、C语言中的const
1.在c语言中 ,const关键字修饰的变量称为常变量,之所以这样说是因为该变量不具有常量性。可以从以下代码编译时编译器给的错误信息看到:
const int a = 10;
int arr[a] = { 0 }; //error
2.数据类型对const而言是透明的
int a = 10;
const int *p = &a;
int const *q = &a;
上面代码中定义了两个指针变量p和q,他们各自都用const关键字来修饰,两种写法的效果都是一样的,数据类型与const修饰的内容无关,也就是说const主要针对的是它所修饰的内容。
3.const修饰它的直接右边,不能做左值(即放在赋值运算符左边)
const int a = 10;
a = 20; //error
const int *p = &a;
*p = 20; //error
通俗来讲,c语言中用const修饰的变量的属性为只读,不允许修改,而赋值运算符的左值是可修改的。
4.权限可以同等或者缩小传递,但不能放大传递(因为放大权限将意味着你可能要修改我,很不安全,这句话对理解const的任意搭配极其重要)。例如,在指针与const结合在一起的时候,谨记不允许泄漏常量的地址给非常量的指针(前一句话是这句话的通俗讲法,因而第一句话极其重要)。下面具体分析:
int a = 10;
int *p1 = &a;
const int *p2 = &a;
int *const p3 = &a;
int *q1 = &a;
const int *q2 = &a;
int *const q3 = &a;
q1 = p1; //权限相同
q1 = p2; //error const在修饰p2的时候强调不可进行解引用操作,
//倘若把p2赋值给q1,q1本身没有任何限制,
//这就属于放大权限,因而会出错
q1 = p3; //互不干扰,因为没涉及到任何修改的操作
q2 = p1; //缩小权限
q2 = p2; //权限相同
q2 = p3; //互不干扰,涉及到的修改操作彼此独立
q3 = p1; //error 与第3条不符
q3 = p2; //error 与第3条不符
q3 = p3; //error 与第3条不符
二、C++中的const
1.与c略有区别的是,c++中const关键字修饰的变量是一个常量,值不允许改变;
const int a = 10;
int arr[a] = { 0 }; //在c++中可以这样做
原因在于编译器在编译期的时候将使用该常量值的地方替换成了常量的值。既然是一个常量,就必须初始化,因为以后没机会对其进行赋值操作,或者说它不能作为左值。
const int a; //error 必须初始化
2.const修饰的数据产生的符号是local的,对外不可见。
fun.cpp
const int A = 10;
main.cpp
#include<iostream>
using namespace std;
extern const int A;
int main()
{
cout << A<< endl;
}
之所以会出现一个无法解析的外部命令的错误提示,存在以下两种可能:
(1)不存在
(2)存在没法用(local)
很显然,我们遇到的是第二种情况。
3.第1点我们说过,c++中用const修饰的变量是一个常量,但在特殊情况(编译器无法确定其值的时候)下它会退化成常变量。
int a = 10;
const int b = a;
int arr[b] = { 0 }; //error 此处的b已经退化为常变量
再看看如下代码:
const int a = 10;
int *p1 = (int*)&a;
*p1 = 20;
cout << *p1 << " " << a << endl; //编译器在编译期在此处进行了值替换,
//a的地址里的值已被修改,但慢了一步
int a = 10;
const int b = a; //此处b已经退化为常变量
int *p1 = (int *)&b;
*p1 = 20;
cout << *p1<<" "<< b<< endl;