指针简介
指针?什么是指针?从根本上看,指针(pointer )是一个值为内存地址的变量(或数据对象)。正如 char
类型变量的值是字符,int
类型变量的值是整数,指针变量的值是地址。
假设一个指针变量名是ptr,可以编写如下语句:
ptr = &pooh; // 把pooh的地址赋给ptr
对于这条语句,我们说 ptr “指向” pooh 。ptr和&pooh 的区别是ptr是变量,而&pooh 是常量。或者,ptr是可修改的左值,而 &pooh 是右值。
还可以把ptr指向别处:
ptr = &bah; // 把ptr指向bah,而不是pooh 现在ptr的值是bah的地址。
要创建指针变量,先要声明指针变量的类型。假设想把ptr声明为储存int类型变量地址的指针,就要使用下面介绍的新运算符。
间接运算符 *
假设已知ptr指向bah,如下所示:
ptr = &bah;
然后使用间接运算符 * (indirection operator)找出储存在 bah 中的值,该运算符有时也称为解引用运算符(dereferencing operator)。不要把间接运算符和二元乘法运算符(*)混淆,虽然它们使用的符号相同,但语法功能不同。
val = *ptr; // 找出ptr指向的值
语句ptr = &bah;
和val = *ptr;
放在一起相当于下面的语句:
val = bah;
地址运算符号:&,后跟一个变量名时,&给出变量的地址。
地址运算符号:*,后跟一个指针名或地址时,*给出存储在指针指向地址上的值。
声明指针
声明指针变量时必须指定指针所指向变量的类型,因为不同的变量类型占用不同的存储空间,一些指针操作要求知道操作对象的大小。另外,程序必须知道储存在指定地址上的数据类型。long
和 float
可能占用相同的存储空间,但是它们储存数字却大相径庭。
下面是一些指针的声明示例:
int * pi; // pi是指向int类型变量的指针
char * pc; // pc是指向char类型变量的指针
float * pf, * pg; // pf、pg都是指向float类型变量的指针
类型说明符表明了指针所指向对象的类型,星号(*)表明声明的变量是一个指针。int * pi;
声明的意思是pi是一个指针,*pi
是int
类型。
- *和指针名之间的空格可有可无。通常,程序员在声明时使用空格,在解引用变量时省略空格。
- pc指向的值(*pc)是
char
类型。pc本身是什么类型?我们描述它 的类型是“指向char 类型的指针”
。 - pc 的值是一个地址,在大部分系统内部,该地址由一个无符号整数表示。但是,不要把指针认为是整数类型。一些处理整数的操作不能用来处理指针,反之亦然。
- ANSI C专门为指针 提供了
%p
格式的转换说明。
使用指针在函数间通信
看一段实例程序:
/* swap3.c -- 使用指针解决交换函数的问题 */
#include <stdio.h>
void interchange(int * u, int * v);
int main(void)
{
int x = 5, y = 10;
printf("Originally x = %d and y = %d.\n", x, y);
interchange(&x, &y); // 把地址发送给函数
printf("Now x = %d and y = %d.\n", x, y);
return 0;
}
void interchange(int * u, int * v)
{
int temp; temp = *u; // temp获得 u 所指向对象的值
*u = *v;
*v = temp;
}
首先看函数调用:
interchange(&x, &y);
该函数传递的不是x和y的值,而是它们的地址。这意味着出现 interchange()原型和定义中的形式参数u和v将把地址作为它们的值。 因此,应把它们声明为指针。由于x和y是整数,所以u和v是指向整数的指针,其声明如下:
void interchange (int * u, int * v)
接下来,在函数体中声明了一个交换值时必需的临时变量:
int temp;
通过下面的语句把x的值储存在temp中:
temp = *u;
u的值是&x,所以u指向x。这意味着用*u即可表示x的值, 这正是我们需要的。
普通变量把值作为基本量,把地址作为通过&运算符获得的派生量,而指针变量把地址作为基本量,把值作为通过*运算符获得的派生量。