指针的语法
声明一个指针变量的语法:
<type> *<ptr_name>;
注:该语法不仅仅指出一个变量为指针,同时表明指针所指向的内存的类型。
指针的指向:变量的地址
指针既可以直接指向新分配的内存,也可以指向一个已经存在的变量。
为了获得变量地址(即变量在内存中的位置),要把符号&放在变量名前。&称为取地址操作符,因为它能返回变量的内存地址:
int x; int *p_x = &x; *p_x = 2; cout << x << endl; //输出x的值等于2
&的作用是得到变量的地址。
(记忆方法:字符“&”的单词 ampersand 和“地址” address 都是以 a 打头的,使用&符号就像是通过网站的地址栏获得该网站的URL)
指针的使用通常可以用来做下列两件事:
- 获得指针中存储的内存地址;
- 获得内存单元中存储的值。
例如,输出指针 p_pointer_to_integer 指向(存储)的地址:
int x = 5; int *p_pointer_to_integer = &x; cout << p_pointer_to_integer; //输出x的地址 //等价于 cout << &x
这个代码片段打印输出变量x的内存地址,而这个变量存储在 p_pointer_to_integer 中。
如果要访问内存单元中存储的值,可以使用 * 操作符,例如:
int x = 5; int *p_pointer_to_integer = &x; cout << *p_pointer_to_integer; //输出5 //等价于 cout << x
代码 *p_pointer_to_integer 表示“到指针所指向的内存,去取出存储在里面的值”。在这个例子中,指针 *p_pointer_to_integer 指向了变量x,而x的值是5,所以输出了数值5。
使用*来获得指针变量指向的地址的值,这一过程称为间接引用指针(为了获得地址中存储的值,我们是通过一个到该内存地址的引用,使用它,间接地到达目的地)。
通过间接引用指针,还可以修改指针地址所指向的变量的值,例如:
int x; int *p_pointer_to_integer = &x; *p_pointer_to_integer = 5; //x的值现在修改为5 cout << x; //输出5
那么,什么时候应该在变量名前加上*号(或&号)?这个很容易出错,为此整理了一下,如下表所示:
操作目的 |
需要的操作符 |
示例 |
声明指针 |
* |
Int *p_x |
获得指针所指向的地址 |
不需要 |
Cout << p_x |
调整指针所指向的地址 |
不需要 |
Int *p_x; p_x = /*address*/ |
获得指针所指向的地址中的值 |
* |
Cout << *p_x |
调整指针所指向的地址中的值 |
* |
*p_x = 5; |
声明变量 |
不需要 |
Int y; |
获得变量的值 |
不需要 |
Int y; cout << y; |
调整变量的值 |
不需要 |
Int y; y=5; |
获得变量的地址 |
& |
Int y; int *p_x; p_x = &y; |
调整变量的地址 |
不可行 |
不可以,变量地址不能更改 |
要记住这张表,切记两个规则:
- 指针存储的是地址。因此,直接使用“裸”指针(即不带任何符号的指针)得到的就是地址。要获得或调整存储在该地址中的值,必须添加额外的*。
- 变量存储的是数据值。因此,直接使用变量得到的就是数据值。而要获得变量的地址,就必须额外添加&。
现在,我们通过一个简单的程序来演示下这些功能:
#include <iostream> using namespace std; int main() { int x; //x为普通变量 int *p_int; //p_int为指向一个整型数的指针 p_int = &x; //将x的地址赋值给p_int cout << "Please enter a number: "; cin >> x; //读入一个值并赋给变量x,这里的x也可以用*p_int来代替 cout << *p_int << ‘\n‘; //使用*来获得指针所指向的变量的值 *p_int = 10; cout << x; //再次输出10 }
第一个cout输出变量x的值。让我们来逐步地执行程序,观察内存是怎样变化的。我们用箭头来表示指针指向的位置,方框中的数字表示非指针变量在内存中的值。
(1)刚开始,我们有一个整型变量x,以及一个指向整型的指针变量p_int。直观上,可以认为现在有两个值未知的变量:
(2)接着,代码通过使用取地址符(&)获得变量x的地址,并将该地址存储到指针p_int 中。
p_int = &x; //将x的地址赋值给p_int
因此,我们可以画一条从变量p_int到变量x的箭头,表示指针p_int指向变量x。
(3)然后用户输入一个数字,存储在变量x中,该存储位置也是p_int所指向的位置。
cin >> x; //读入一个值并赋给变量x,这里的x也可以用*p_int来代替
简单起见,我们假设用户输入数字5.现在内存的情况变成了这样:
(4)接着,下一行代码将*p_int传给cout。p_int间接引用了p_int,它会检查p_int中的地址,并且到该地址中取出其变量值。
cout << *p_int << ‘\n‘; //使用*来获得指针所指向的变量的值
(5)最后的两行语句表面,通过指针可以修改变量原来的值。这个语句将值10存储到p_int所指向的内存中,也就是存储着变量x的值的内存。
*p_int = 10;
总结
在学习数据结构的时候,发现对指针这块还是有些模糊,于是回顾了一下指针,将其收获和感受写了下来。
此次学习使我了解了使用指针的好处之一就是方便修改其所指向内存的值;清楚了什么时候应该在变量名前加上*号(或&号);当搞不明白使用指针时内存的变化过程时,可以先绘制出内存的初始状态,配合箭头图逐步执行程序,内存的变化过程也就一目了然了,每当指针的指向改变时,便绘制新的箭头,每当变量的值发生变化时,更新它的值。