1
第九讲 指针
2
指针是 C语言中的一个重要概念。掌握指针的用
法,可使程序简洁、高效、灵活,但并不难学。
为了了解什么是指针,先看一个小故事
地下工作者阿金接到上级指令,要去寻找打开
密电码的密钥,这是一个整数。几经周折,才探知
如下线索,密钥藏在一栋三年前就被贴上封条的小
楼中。一个风雨交加的夜晚,阿金潜入了小楼,房
间很多,不知该进哪一间,正在一筹莫展之际,忽
然走廊上的电话铃声响起。艺高人胆大,阿金毫不
迟疑,抓起听筒,一个陌生人说:, 去打开 211房
间,那里有线索, 。阿金疾步上楼,打开 211房间,
用电筒一照,只见桌上赫然 6个大字:地址 1000。
阿金眼睛一亮,迅速找到 1000房间,取出重要数据
66,完成了任务。
3
我们画出下图
1000 … 66 …
211 1000
P
说明,
1、数据藏在一个内存地址单元中,地址是 1000。
2、地址 1000又由 P单元所指认,P单元的地址为 211。
3,66的直接地址是 1000; 66的间接地址是 211; 211中
存的是直接地址 1000。
4、称 P为指针变量,1000是指针变量的值,实际上是有
用数据藏在存储器中的地址。
4
指针变量 ——用来存放另一变量地址的变量
变量的指针就是变量的地址。
1、指针的概念
指针 是一种特殊的变量,特殊性表现在类型和值上。
从变量讲,指针也具有变量的三个要素,
? ( 1)变量名,这与一般变量取名相同,由英文字符开始。
? ( 2)指针变量的类型,是指针所指向的变量的类型,而不
是自身的类型。
? ( 3)指针的值是某个变量的内存地址。
5
从上面的概念可知,指针本身类型是 int型,因为任何内存地
址都是整型的。但是指针变量的类型却定义成它所指向的
变量的类型。
2、指针的定义(说明,先说明后引用)
例如,
int *p,*q; // 定义 p,q为指向整数类型变量的指针
float *point; // 定义 point为指向 float型变量的指针
double *pd; // 定义 pd为指向 double型数组的指针
int (*pa)[10]; // 定义 pa为指向 int型数组的指针
int (*pu)(); // 定义 pu为指向 int型函数的指针
int **qq; // 定义 qq为指向 int型指针的指针
还有指向结构、联合的指针,后面再介绍
6
3、指针赋值

int akey; // 定义一个整型变量 akey
int *p,*q; // 定义 p,q为指向整型变量的指针变量
akey= 66; // 将变量 a的地址赋给 p,这时见图 1
q = p; // 将 p的值赋给 q,见图 2
66
&a
p a
&p
p 变量的地址
&a
a 变量的地址
图 1 的说明:将 a 变量的地址赋给指针 p,意味着让指针
p 指向 a
图 1
7
66
&a
p a
图 2 的说明:当着执行 q = p; 之后,p 中所存的 a 变量的
地址值,也就被放到 q 变量中,意味着让指
针 q 也指向 a
图 2
&a
q
&p
&q
q =p ;
8
// 指针 1.c
#include <stdio.h> //预编译命令
void main() //主函数
{ //函数体开始
int a[5]={0,1,2,3,4}; //定义数组,赋初值
int *p1,*p2; //定义指针变量
p1=&a[1]; //赋值给指针变量,让 p1指向 a[1]
p2=&a[2]; //赋值给指针变量,让 p1指向 a[2]
printf("a[1]=%d;a[2]=%d\n",*p1,*p2); //输出 a[1]和 a[2]的值
}
9
说明:见图
0 1 2 3 4
&a[0] &a[1] &a[2] &a[3] &a[4]
&a[1] &a[2]
&p1 &p2
p1 p2
p1和 p2分别指向 a[1],a[2],这里
? & —— 取地址运算符
? * —— 指针运算符(间接访问运算符)
? *p1——间接访问 p1所指向的内存单元,当然是输出 a[1]的值
? *p2——间接访问 p2所指向的内存单元,当然是输出 a[2]的值
10
// 指针 2.c
#include <stdio.h> //预编译命令
void main() //主函数
{ //函数体开始
int akey,b; //定义整型变量
int *p,*q; //定义指针变量
akey=66; //赋值给变量 akey
p=&akey; //赋值给指针变量 p,让 p指向变量 akey
q=&b; //赋值给指针变量 q,让 q指向变量 b
*q=*p; //将 p所指向的 akey的值赋给 q所指向的变量 b
printf("b=%d\n",b); //输出 b的值
printf("*q=%d\n",*q); //输出 b的值
} //函数体结束
4、向指针所指向的内存单元赋值
11
66
66
& ak ey
p
& ak e y
*q =*p
&a
q
&b
12
// 指针 3.c
#include <stdio.h> //预编译命令
void main() //主函数
{ //函数体开始
int a[5]={1,3,5,7,9}; //定义数组,赋初值
int *p; //定义指针变量
int i; //定义整型变量
p=a; //赋值给指针变量,让 p指向 a数组
for(i=0;i<5;i=i+1)
{ //循环体开始
printf("a[%d]=%d\n",i,*p);//输出 a数组元素的值
p=p+1; //指针变量加 1
} //循环体结束
} //函数体结束
5、指针与数组
先看一个程序
13
说明
? (1) p=a; 这里数组名作为数组的起始地址,即 a[0]的地址。
因此 p=a 等效于 p=&a[0];
? (2) p=p+1; 如 p指向 a[0],则 p=p+1之后,p指向 a[1]
? (3) 如果 p=a 等效于 p=&a[0];
则 p=a+4 等效于 p=&a[4];
a[0]
a[1]
a[2]
a[3]
a[4]
*p
*(p+1)
*(p+2)
*(p+3)
*(p+4)
p
p+1
p+2
p
p+1
p+2
等效
14
// 指针 4.c
#include <stdio.h> //预编译命令
void main() //主函数
{ //函数体开始
int a[5]={1,3,5,7,9}; //定义数组,赋初值
int *p; //定义指针变量
int i=0; //定义整型变量,赋初值
for(p=a;p<a+5;p=p+1) //赋值给指针变量,让 p指向 a数组
{ //循环体开始
printf("a[%d]=%d\n",i,*p); //输出 a数组元素的值
i=i+1; //让 i加 1
} //循环体结束
} //函数体结束
做下面的实验
15
// 指针 5.c
#include <stdio.h>
void main()
{
char *p; // 定义指向字符类型的指针变量 p
static char s[] =,abcdefgh”; // 定义字符数组,并赋值
p=s; // 数组名是一个常量指针,
// 它指向该数组首地址
while (*p != ?\0?) // 当 p所指向的数组元素不为 ?\0?时
{
p=p+1; // 让指针加 1
}
printf(“字串长度为 %d\n”,p-s);// 输出字串长
}
数组名是一个常量指针,指向该数组的首地址,例
16
0 1 2 3 4 5 6 7 8
a b c d e f g h \0 s
s p
图中数组的首地址是 s[0]的地址,即 &s[0]。 s可看
作是指向 s[0]的指针。 s是不会动的,是常量指
针。
17
// 指针 6.c
#include <stdio.h> //预编译命令
void main() //主函数
{ //函数体开始
static char shuzi[]=“987654321”; //定义数组,
// 赋初值为数字字符串
char *p=&shuzi[8]; //让指针 p指向 shuzi[8]元素,
// 该处是字符‘ 1?
do // 直到型循环
{ // 循环体开始
putchar(*p); // putchar函数的作用是向终端
// 输出一个字符,该字符由 p指向
p=p-1; // 让 p减 1
} // 循环体结束
while (p>=shuzi); // 当 p>=shuzi时,继续循环
putchar(?\n?); // 换行
}
数组名是一个常量指针,指向该数组的首地址,例
18
结 束