文章目录
0 前言
指针是C语言的一大特性,指针是一种 “ 指向(pointer to)” 另外一种类型的复合类型。指针就是一个存放内存地址的变量。指针本身就是一个对象,允许对指针赋值和拷贝,而且指针在生命周期内它可以先后指向几个不同的对象。指针无需在定义时赋初值。以下图示是将要讲述的关于指针的内容,可以结合文字进行理解。
1 指针的定义
指针的声明形如 *ptr,其中 ptr 是变量名。需要注意的是如果在一行语句中声明了几个指针变量,每个变量前面都必须有符号 *。
int *ptr1, *ptr2; // ptr1和ptr2都是指向 int 型对象的指针
double dp, *dp2; // dp2 是指向 double 型对象的指针,dp 是 double 型对象
1.1 获取对象的地址
指针存放某个对象的地址,要想获取对象的地址,需要使用取地址符 &。
int ival = 42;
int *p = &ival; // p 存放变量 ival 的地址,p 是指向变量 ival 的指针
1.2 利用指针访问对象
如果指针指向了一个对象,则允许使用解引用符 * 来访问该对象。
int ival = 42;
int *p = &ival;
cout << *p; // 解引用得到指针 p 所指的对象,输出42
1.3 空指针
空指针不指向任何对象,以下列出几个生成空指针的方法:
int *p1 = nullptr; // 等价于 int *p1 = 0;
int *p2 = 0; // 直接将 p2 初始化为字面常量0
// 需要首先包括头文件 #include <cstdlib>
int *p3 = NULL;
得到空指针最直接的办法就是字面值 nullptr 来初始化,这是 C++11 \texttt{C++11} C++11 标准引入的一种方法。nullptr 是一种特殊类型的字面值,它可以被转化成任意其他类型的指针。另一种对空指针的定义方法如对 p2 的定义,也可以通过指针初始化为字面值 0 来生成空指针。
2 const pointer (常量指针)
常量指针必须初始化,一旦完成初始化,它的值就不能再改变了。
int errNum = 0;
int *const curErr = &errNum; // curErr 一直指向 errNum
*curErr = 10; // 正确的,指针指向的值可以改变
要想理解 curErr 的类型是什么,一个通用的阅读规则是 从右往左阅读。离 cueRrr 最近的符号是 const,表名 curErr是一个常量对象,对象的类型由声明符的其他部分确定。声明符中从右往左的下一个符号是 *,表名 curErr 是一个常量指针。最后,该声明语句的基本数据类型确定了常量指针指向的是一个 int 对象。
指针本身是一个常量意味着该指针本身的值不可以改变,但是指针指向的值是可以改变的。
3 pointer to const (指向常量的指针)
要想存放常量对象的地址,只能使用指向常量的指针。
const int a = 10;
// p 是指定 const int 型对象的指针
const int *p = &a; // p pointer to const int ,指针指向整型常量
*p = 42; // 错误的,指向常量的指针不能通过该指针改变对象的值
利用该阅读规则理解 p 的类型:离 p 最近的是一个 *,表名 p 是一个指针,该声明语句的基本数据类型确定了指针p指向的是一个 int 类型常量即整型常量对象。
指针 p 指向的是一个整型常量对象,表名该指针指向的值是不可以改变的,准确的说是不能通过该指针改变整型常量对象的值。
我们不能解引用指向常量的指针并改变指针所引用的值,但可以改变指针。指针的值不是常量。指针可以修改为引用另一个整数常量或者普通整数,这样不会有问题。声明只是限制我们不能通过指针来修改引用的值。
4 const pointer points to const (指向常量对象的常量指针)
const double pi = 3.14; // pi 是双精度浮点类型常量对象
cont double *const pip = π // pip 是一个指向常量对象的常量指针
根据阅读规则可以知道,pip 是一个常量指针,它指向的对象是一个双精度浮点型常量。
指向常量对象的常量指针表名,指针本身的值不可以改变,指针指向的值也不可以改变。
5 总结
- 指针就是一个存放内存地址的变量;
- 从右往左读,可以比较清晰的理解指针的类型和指向的类型;
- 指针指向的对象是常量类型表示不能通过指针更改指向的对象的值,指针的值不是常量,可以指向别的普通变量或者常量变量。