1.const与指针
1.1const在c语言和c++中的区别
我们先看下面这段简单的代码:
const int n=10;
int arr[n]={1,2};
同样的一段代码,在C语言中编译是不能通过的,而在C++中,编译却可以通过,其中的主要原因是C语言和C++对const的处理不同 。
在C++中,编译器遇到const修饰的变量处理方式是直接替换,什么意思,我们举例说明:
const int n=10;
int b=n;
在C语言中访问n的内存空间赋值给b,在C++中看见n,会替换成10,这样是不是理解了。
我们继续拿代码举例:
int main()
{
const int a=10;
int b=0;
int *ip=(int *)&a;
*ip=100;
b=a;
printf("a=%d,b=%d,*ip=%d\n",a,b,*ip);
return 0;
}
我们通过改变文件后缀名来分别运行查看结果,现在可以自己进行思考,看一下结果与答案是否正确。
在.c文件中(C语言),运行结果如下:
a=100,b=100,*ip=100;
在.cpp文件中,运行结果如下:
a=10, b=10, *ip=100;
总结:在C++中,编译器遇到const修饰的变量处理方式是直接替换。
1.2const与指针的关系
我们先看以下代码:
int a = 10;
int* p = &a;//1
const int* p1 = &a;//2
int const* p2 = &a;//3
int* const p3 = &a;//4
const int* const p4 = &a;//5
const我们在学C语言中已经学到过,在这里 我们不再做 过多解释,当const 与指针结合起来,难度会少些增加,先看第一个代码,也是我们最常见的代码,定义一个普通指针指向变量a的地址。
第2个代码:
我们在最前面加上const修饰后,此时const修饰的是*p1,也就是说我们不能通过*p1去改变变量a的值,但是我们可以通过p1去指向其他的变量;
第3个代码:
和第二个代码完全一样,修饰的是*p2;
第4个代码:
此时const修饰的是p3,也就是说我们可以通过*p3去改变变量a的值,但是我们不能通过p3去指向其他变量,只能指向变量a;
第5个代码:
此时cosnt既修饰*p4也修饰p4,也就是说我们既不可以通过*p3去改变变量a的值,我们也不能通过p3去指向其他变量,只能指向变量a;
我们再继续深入理解一下,如果我们对变量加上const,再用指针去指向,这里直接给出答案:
p1编译不通过,可以这样理解,变量a是const int类型,而指针p1是int*,类型不匹配;其实真正不通过的原因是不安全,变量a加上const修饰后,变量a的值不能改变,用普通指针p1可以通过*p1去改变a的值,所以编译不通过。
p3不通过的原因也是一样的,可以通过*p3去改变变量a的值,因为cosnt修饰的是p3不是*p3;
接下来就是重头戏,继续增加难度,我们看下边的代码,尝试去判断一下。
我们看以上图片,可以思考一下,指针s1,s2,s3,s4哪些可以编译通过,哪些不可以;
需要了解的知识点:同类型指针的赋值兼容规则:能力强的指针赋值给能力收缩的指针;
左图:
s1不通过,s2通过,s3不通过,s4通过
观察指针p,不能通过*p去改变变量a的值,但是可以指向其他变量;s1能力比p的大,不可以,s2可以(能力相等),s3虽然不能指向其他变量,但是能通过*s3改变变量的值,不安全,因此也不可以,s4可以(s4能力比p小)
右图:
都通过,这里解释一下s1为什么会通过,s1的能力不是比p大吗?首先观察p,p可以通过*p去改变变量的值,但是不能指向其他变量;s1也可以通过*s1去改变变量的值,但是s1指向其他变量时,并不影响p的指向,能力没有扩展 ,是安全的,所以编译可以通过,s2,s3,s4也是一样,s的改变并不影响p的改变,所以都通过。
需要仔细理解同类型指针的赋值兼容规则:能力强的指针赋值给能力收缩的指针;这句话。