阅读 ‧ 电子书库 总结:与指针相关的运算符
地址运算符:
&
总体注解:
后跟一个变量名时,&给出该变量的地址。
例如:
&nurse表示变量nurse的地址。
间接运算符:
*
总体注解:
当后跟一个指针名或地址时,*给出存储在被指向地址中的数值。
例如:
阅读 ‧ 电子书库
上述语句实现的功能是把数值22赋给变量val。
9.7.2 指针声明

我们已讲述了int类型变量以及其他基本数据类型变量的声明方法。那么应该如何声明指针变量呢?您也许会猜想其声明形式如下:

阅读 ‧ 电子书库

为什么不能这样声明?因为这对于声明一个变量为指针是不够的,还需要说明指针所指向变量的类型。原因是不同的变量类型占用的存储空间大小不同,而有些指针操作需要知道变量类型所占用的存储空间。同时,程序也需要了解地址中存储的是何种数据。例如,long和float两种类型的数值可能使用相同大小的存储空间,但是它们的数据存储方式完全不同。指针的声明形式如下:

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

阅读 ‧ 电子书库

类型标识符表明了被指向变量的类型,而星号(*)表示该变量为一指针。声明int * pi;的意思是pi是一个指针,而且*pi是int类型的(请参见图9.5)。

阅读 ‧ 电子书库

图9.5 指针的声明和使用

*和指针名之间的空格是可选的。通常程序员在声明中使用空格,而在指向变量时将其省略。

pc所指向的值(*pc)是char类型的。而pc本身又是什么类型?我们把它描述为“指向char的指针”类型。pc的值是一个地址,在大多数系统内部,它由一个无符号整数表示。但是,这并不表示可以把指针看作是整数类型。一些处理整数的方法不能用来处理指针,反之亦然。例如,可以进行两整数相乘,而指针则不能。因此指针的确是一种新的数据类型,而不是一种整数类型。所以,正如前面提到的,ANSI C专门为指针提供了%p输出格式。

9.7.3 使用指针在函数间通信

我们只是刚刚接触到丰富有趣的指针知识的很小一部分,但这里我们的重点是讲述如何通过指针解决函数间通信问题。在程序清单9.15中的程序中,函数interchange()使用了指针参数,我们将对该函数进行详细的讨论。

程序清单9.15 swap3.c程序

阅读 ‧ 电子书库

对全部源文件进行编译后,该程序能否正常运行?

阅读 ‧ 电子书库

阅读 ‧ 电子书库

答案是肯定的,结果如上所示。

下面我们分析程序清单9.15的运行情况。首先,函数调用语句如下:

阅读 ‧ 电子书库

可以看出,函数传递的是x和y的地址而不是它们的值。这就意味着interchange()函数原型声明和定义中的形式参数u和v将使用地址作为它们的值。因此,它们应该声明为指针。由于x和y都是整数,所以u和v是指向整数的指针。其声明如下:

阅读 ‧ 电子书库

接下来,函数体进行如下声明:

阅读 ‧ 电子书库

从而提供了所需的临时变量。为了把x的值存在temp中,需要使用以下语句:

阅读 ‧ 电子书库

注意,因为u的值是&x,所以u指向x的地址。这就意味着*u代表了x的值,而这正是我们需要的数值。不要写成如下这样。

阅读 ‧ 电子书库

上面的语句中,因为赋给变量temp的只是x的地址而不是x的值,所以不能实现数值的交换。

同样,把y的值赋给x,需使用下面的语句:

阅读 ‧ 电子书库

其执行结果相当于:

阅读 ‧ 电子书库

在示例程序中,我们用一个函数实现x和y的数值交换。首先函数使用x和y的地址作为参数,这使它可以访问x和y变量。通过使用指针和运算符*,函数可以获得相应存储地址的数据,从而就可以改变这些数据。

在ANSI原型中可以省略变量名称。这样,函数原型可以按如下形式进行声明:

阅读 ‧ 电子书库

通常情况下,可以把关于变量的两类信息传递给一个函数。如果函数调用形式为:

阅读 ‧ 电子书库

这时传递的是x的值。但是如果使用下面这种函数调用形式:

阅读 ‧ 电子书库

那么会把x的地址传递给函数。第一种调用形式要求函数定义部分必须包含一个和x具有相同数据类型的形式参数。如下所示:

阅读 ‧ 电子书库

而第二种形式要求函数定义部分的形式参数必须是指向相应数据类型的指针:

阅读 ‧ 电子书库

使用函数进行数据计算等操作时,可以使用第一种调用形式。但是,如果需要改变调用函数中的多个变量的值时,就需要使用第二种调用形式。其实使用scanf()时已经使用了第二种形式。例如,当需要为变量num读取一个数值时,可以调用函数scanf(“%d”,&num)。该函数调用的意思是先读取一个数值,然后将其存储到通过参数获得的地址中。

尽管interchange()只使用局部变量,但是通过使用指针,该函数可以操作main()中的变量的值。

使用过Pascal和Modula-2的读者可能已经看出第一种调用形式和Pascal中的值参数相同,而第二种形式与Pascal中的变量参数相似(尽管不完全相同)。对于BASIC程序员来说,整个程序可能比较难于理解。如果您感到本节晦涩难懂,那么可以进行一些实际的编程练习,这时就会发现使用指针非常简单方便(请参见图9.6)。

阅读 ‧ 电子书库

图9.6 字节编址的系统(如IBM PC)中的名称、地址和数值