目录

这篇文章用于记录我学习 C++ 过程中一些值得记录的东西,以便理清思路、检验所学。也就是说,它并不是一篇按部就班的 C++ 教程,估计以后我也基本都会是这写一块那写一块这样。不过虽然这一块一块的知识拼不出一幅完整的拼图,但是每一块本身的内容可以说基本都是完整的。如果感兴趣的话,衷心希望这些东西能对你有所帮助。

指针

说到指针,先提一下变量。变量的值显然被存储于计算机内存中的某一处,对于存储具体的物理地址我们编写的 C++ 程序不需要知道,我们的程序只需要知道我们给变量起的名字也就是标识符(identifier),便可以访问变量的值。至于怎么样才能通过标识符找到相应的物理地址?这活儿是操作系统负责干的,我们不要多管闲事。

变量说完说指针,前面说过,我们要使用一个变量时只需要提供标识符即可,操作系统会负责根据标识符找到对应的物理地址,从而访问那个物理地址里存储的值。而指针存在的意义就是,指针本身便是一个地址,我们可以直接通过指针去访问那个地址里存储的值。但在了解指针之前,我们要先了解两个互补的运算符。

首先是取地址符( & )。我们可以通过把取地址符( & )放在变量的名称前来获得一个变量的地址。示例:

var = 25;
address = &var;
value = var

假设这几个变量都已经被合理的声明,且 var 的物理地址是 1775。则第二行代码的意思是让 address 存储了 var 的物理地址 1775,第三行代码则是一个正常的赋值操作,不多解释。类似于 address 这种存储了另一个变量的物理地址的变量,我们便称其为“指针”。

指针不光可以用来存储其他变量的地址,它还可以直接操作指针指向的那个地址里存储的值(好绕啊…下文统一一下口径:“指针的值”是一个地址,“指针指向的值”是那个地址里的存储的值)。那么怎么才能操作指针指向的值呢?答案是通过解引用运算符( * )。示例:

value_2 = *address;

因为 address 的值是 1775,而地址 1775 指向的值是 25。所以 value_2 的值便是 25。注意要明确区分 address*addressaddress 指的是地址值 1775,而 *address 是指存储在地址 1775 中的值。

以防大家看的迷瞪,我们先复习一下再继续往下说,假如:

var = 25;
address = &var;

则下面给出的这四个表达式均为真,都明白了就基本没问题了:

var == 25
&var == 1775
address == 1775
*address == 25

现在我们开始尝试去声明一个指针,指针的声明语句格式如下:

类型说明符 + * + 标识符;

需要特别强调的是,上面那个 类型说明符 指的其实并不是指针本身的类型,而是指针指向的值的类型。指针作为一个复合类型,类型说明符+* 这个复合类型说明符才指的是指针本身的类型。理解这句话对以后理解常量指针和指向常亮的指针的声明有很大的帮助。

举几个例子:

int * number;
char * character;
double * decimals;

这是三个指针的声明,如前所说,上面三条声明语句的 intchardouble 便是指针指向的值的类型。而这三个指针本身的类型分别是:int*char*double*

另外要注意的是,如上所说指针是一种复合类型,在这里 * 是复合类型说明符的一部分,就像上文提到的 int*char*double*。所以星号 * 在出现在指针的声明部分里时,只用来表示声明的是一个指针。我们不应该把这里的 * 与之前看到的解引用操作符混淆,这俩只是用相同符号表示的两种不同的东西而已。

最后举一个复杂点的例子,加深一下理解:

#include 
using namespace std;

int main ()
{
    int firstvalue, secondvalue;	//声明变量,但不初始化
    int *p1, *p2;					//声明指针,但不初始化
    p1 = &firstvalue;				//初始化,使用取地址符(&)为p1分配firstvalue的地址
    *p1 = 10;						//初始化,p1指向的值被初始化为10。因为此时p1指向firstvalue的内存位置,所以这实际上修改了firstvalue的值。
    p2 = &secondvalue;				//解释同上
    *p2 = 20;						//解释同上
    *p2 = *p1;						//赋值,改变的是指针指向的值,secondvalue现在等于10
    p2 = p1;						//赋值,改变的是指针本身的值,p2现在指向&firstvalue
    *p2 = 20;						//给p2现在指向的firstvalue赋值为20

    cout << "firstvalue的值为" << firstvalue << '\n';
    cout << "secondvalue的值为" << secondvalue << '\n';
    return 0;
}

注释已经写得很清楚了,输出为:

firstvalue的值为20
secondvalue的值为10

未完待续…