day2:指针常量和常量指针
指针常量和常量指针是我们在学习c语言过程中比较容易混淆的概念,下面我来简单介绍这两个的区别和使用的例程:
1.常量指针
常量指针的定义方法有两种,两种均可以:
const int *p;
int const *p;
常量指针的作用是保护指针当前所指向地址的值不能发生变化,但是指针的指向可以改变,例如:
我们定义一个整型的常量指针,将它指向i的地址,那此时*p对应的值就是1;
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=2;
const int *p=&i;
printf("%d\n",*p);
return 0;
}
如果我们试图改变指针当前地址的值,那程序就会报错,如果我们 运行一下程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=2;
const int *p=&i;
*p=2;//改变*P的值
printf("%d\n",*p);
return 0;
}
编译报告如下:
其实我们可以将常量指针简单理解为 const关键字修饰了int p, 程序不能改变p的值;
但是我们一开始就说过,常量指针并不限制指针的指向,我们仍然可以改变指针的指向,一下程序编译后*p的值为10;
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=10;
const int *p=&i;
p=&a;
printf("%d\n",*p);
return 0;
}
2.指针常量
指针常量的定义方法如下:
int *const p;
指针常量的作用是保护指针的指向不能改变,而指针所指向地址的值可以变化;
有了上面的理解,接下来的验证方法也是相似的。
首先我们看一个基础的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=10;
int *const p=&i;
printf("%d\n",*p);
return 0;
}
运行程序,输出的值为1;
接下来我们验证是否可以改变指针当前地址的值,程序如下:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=10;
int *const p=&i;
*p=2;
printf("%d\n",*p);
return 0;
}
运行结果为2;*p可以被改变。
最后我们验证一下指针的指向能不能被改变:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=1;
int a=10;
int *const p=&i;
p=&a;
printf("%d\n",*p);
return 0;
}
程序报错:
3.两个const修饰
最后我们再看一行代码
const int *const p=&i;
哎,有了上面两个知识点的铺路,再看到这行代码时,是不是就胸有成竹了。没错,我们可以理解为第一个const修饰的是:int *p,第二个const修饰的是p,所以此时指针的指向和指针当前地址的值均不能被改变。验证的方法和上面类同,这里就不过多赘述了(偷个懒)。
4.具体运用
其实常量指针和指针常量再封装函数的时候有大量的运用例子,比如我们常用的strcpy()函数:
可以看到第一个入口参数并没有用const修饰,而第二个入口参数用了const chan *src,为什么呢。C 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。用const 修饰 char *src,保证我们所复制的目标值不能被改变,而第一个参数本来就是要被新的内容所覆盖的,所以就不用const来修饰。这种封装方式也是我们日后学习中要学会借鉴的。
5.总结
要分清楚那个值不能被改变,我们只需要看const后面修饰的是什么。常量指针(const int * p)const后面修饰的是int * p,所以p不能被改变,这里的p是地址存放的值,所以值不能被改变;而指针常量(int *const p)const后面修饰的是p,所以p不能被改变,这里的p就是地址,也就是指针的指向。