4.2.3 使用指针
如何获得变量的地址,并将其存入某个指针变量都已经讲解清楚了,但真正有趣的是如何使用指针。指针的重要用途是存取指针所指变量中的数据值,这需要使用间接运算符*。
1. 间接运算符
将间接运算符*与某个指针一起使用,可以存取该指针指向的变量的内容。"间接运算符"的名称源于间接存取数据的事实。该运算符又名解除引用运算符,而存取指针所指的变量中数据的过程被称为解除对指针的引用。
该运算符可能使人混淆,因为相同的符号*现在有多种不同用途。星号*是乘法运算符,还是间接运算符,此外还用于指针的声明。我们每次使用*符号时,编译器都能根据上下文区分其意义。当我们使两个变量相乘时-- 比如A*B,该表达式除了是乘法操作以外,没有任何其他有意义的解释。
2. 需要使用指针的原因
为什么一定要使用指针?毕竟,取出我们已经知道的某个变量的地址,然后将其放入某个指针内,以便能够解除对该指针的引用,看起来似乎是完全不必要的额外开销。但指针实际上非常重要,原因不止一种。
我们可以使用指针符号处理数组中存储的数据,相应的执行速度往往比使用数组符号要快。另外,当我们稍后学习如何定义自己的函数时,将看到指针被广泛使用,以便能够在函数内部访问在函数外部定义的大块数据-- 比如数组。但最重要的一点是使我们能够动态地-- 即在程序执行过程中,给变量分配存储空间。这种功能使程序可以根据实际的输入,来调整自己的内存使用量。因为我们预先不知道将动态创建多少个变量,所以首选方法是使用指针。因此,我们应该确保真正掌握指针的用法。
试一试:使用指针
在下面的示例中,我们可以试一试指针操作的各种用法。
- //Ex4_05.cpp
- // Exercising pointers
- #include <iostream>
- using std::cout;
- using std::endl;
- using std::hex;
- using std::dec;
-
- int main()
- {
- long* pnumber = NULL; // Pointer declaration & initialization
- long number1 = 55, number2 = 99;
-
- pnumber = &number1; // Store address in pointer
- *pnumber += 11; // Increment number1 by 11
- cout << endl
- << "number1 = " << number1
- << " &number1 = " << hex << pnumber;
-
- pnumber = &number2; // Change pointer to address of number2
- number1 = *pnumber*10; // 10 times number2
-
- cout << endl
- << "number1 = " << dec << number1
- << " pnumber = " << hex << pnumber
- << " *pnumber = " << dec << *pnumber;
-
- cout << endl;
- return 0;
- }
在笔者计算机上,本示例产生下面的输出:
- number1 = 66 &number1 = 0012FEC8
- number1 = 990 pnumber = 0012FEBC *pnumber = 99
示例说明
本示例没有输入,所有操作都是用变量的初值执行的。将number1的地址存入指针pnumber之后,number1的值通过下面这条语句中的指针而间接增加:
- *pnumber += 11; // Increment number1 by 11
注意:
当首次声明指针pnumber时,我们将其初始化为NULL。我们将在下一小节讨论指针初始化的问题。
间接运算符使我们将pnumber所指变量-- 即number1-- 的内容加上11。如果忘记在这条语句中写上*号,则计算机将使该指针存储的地址加上11。
number1的值以及存储在pnumber中的number1的地址都被显示出来。程序使用hex操作符,以生成十六进制形式的地址输出。
通过使用hex操作符,我们可以使普通整型变量的值也以十六进制的形式输出。只要我们以与发送endl完全相同的方式将hex发送到输出流中,则所有后面跟着的输出就都是十六进制。如果我们希望后面的输出再变为十进制,则需要在下一条输出语句中使用dec操作符,将输出再次切换回十进制模式。
在第一行输出之后,pnumber的内容被设置为number2的地址。变量number1的值则变为number2的10倍:
- number1 = *pnumber*10; // 10 times number2
计算是借助于指针通过间接访问number2的内容进行的。第二行输出显示出计算的结果。
您在输出中看到的地址值可能与上面的示例输出完全不同,因为这些值反映的是内存中加载该程序的位置,这取决于操作系统的配置情况。地址值的前缀0x表明它们是十六进制数。注意,地址&number1和pnumber(包含&number2)相差4个字节。这表明number1和number2占用着相邻的存储单元,因为每个long类型变量占用4个字节。