第九章 指针
9.1 地址指针的基本概念
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。内存区的每一个字节有一个编号,这就是 “地址” 。
由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元,将地址形象化地称为“指针”。
存储单元的地址和存储单元的内容是两个不同的概念。在程序中一般是通过变量名来引用变量的值。
直接按变量名进行的访问,称为“直接访问”方式。还可以采用另一种称为“间接访问”的方式,即将变量的地址存放在另一变量(指针变量)中,然后通过该指针变量来找到对应变量的地址,从而访问变量。
指针
int i=1,j=2,k=3;
int *i_pointer; //定义了一个变量i_pointer,用来存放整型变量的地址
i_pointer=&i; //把i的地址赋给i_pointer
i_pointer的值是变量i的地址(2000),这样就在i_pointer和变量i之间建立起一种联系:即通过i_pointer能知道i的地址,从而找到变量i的内存单元。
如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”,指针变量就是地址变量(存放地址的变量)。上述的i_pointer就是一个指针变量,指针变量的值(即指针变量中存放的值)是地址(即指针)。
9.2 指针变量
9.2.1 怎样定义指针变量
类型名*指针变量名;
(int *pointer_1,*pointer_2;
)
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
定义指针变量时注意:
(1)指针变量前面的 “ * ” 表示该变量为指针变量。指针变量名字不包含 “ * ”。
(2)在定义指针变量时必须指定基类型。一个指针变量只能指向同一个类型的变量,不能忽而指向一个整型变量,忽而指向一个实型变量。
对指针变量赋值时注意:
(1)指针变量中只能存放地址(指针),不要将一个整数赋给一个指针变量。
(2)赋给指针变量的地址不能是任意的类型,而只能是与指针变量的基类型具有相同类型的变量的地址。
一个地址型的数据实际上包含三个信息:
(1)表示内存编号的纯地址;
(2)它本身的类型,即指针类型(地址类型),而不是数值数据;
(3)它指向的存储单元中存放的是什么类型的数据,即地址的基类型。
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
9.2.2 怎样引用指针变量
①给指针变量赋值。
②引用指针变量。
③引用指针变量的值。
int a,*p;
p=&a; //把a的地址赋给指针变量p
printf("%d",*p); //以整数形式输出指针变量p所指的变量的值,即a的值
*p=1; //将整数1赋给p当前所指向的变量,由于p指向变量a,相当于把1赋给a,即a=1
printf("%o",p); //以八进制形式输出指针变量p的值,由于p指向a,相当于输出a的地址,即&a
注意
要熟练掌握两个有关的运算符
① & 取地址运算符。&a是变量a的地址。
② * 指针运算符(或称“间接访问”运算符),*p代表指针变量p指向的对象。
p指地址,*p指的是所指变量的值
【例9.1】有两个整型变量,要求分别用直接访问的方法输出它们的值。
#include<stdio.h>
int main()
{
int a,b;
int *pointer_a,*pointer_b; //定义两个int*型变量
a=100;b=10;
pointer_a=&a; //把变量a的地址赋给pointer_a
pointer_b=&b; //把变量b的地址赋给pointer_b
printf("a=%d,b=%d\n",a,b); //用直接访问输出变量a和b的值
printf("*pointer_a=%d,*pointer_b=%d\n",*pointer_a,*pointer_b);//用间接访问输出变量a和b的值
return 0;
}
【例9.2】输出a和b两个整数,按先大后小的顺序输出a和b,要求用指针的方法处理。
**解题思路:**可以用指针变量分别指向a和b,如果a<b,不交换a和b的值,而交换两个指针变量的值,即交换它们的指向。
#include<stdio.h>
int main()
{
int *p1,*p2,*p,a,b; //p1,p2的类型是int*类型
scanf("%d,%d",&a,&b); //输入两个整数
p1=&a; //使p1指向变量a
p2=&b; //使p2指向变量b
if(a<b) //如果a<b
{
p=p1;p1=p2;p2=p;} //使p1与p2的值互换
printf("a=%d,b=%d\n",a,b); //输出a,b
printf("max=%d,min=%d\n",*p1,*p2); //输出p1和p2所指向的变量的值
return 0;
}
改地址
9.2.3指针变量作为函数参数
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
函数的调用可以(而且只可以)得到一个返回值(即函数值),而使用指针变量做参数,可以得到多个变化了的值。如果不用指针变量是难以做到这一点的。要善于利用指针法。
如果想通过函数调用得到n个要改变的值,可以这样做:
①在主调函数中设n个变量,用n个指针变量指向它们;
②设计一个函数,有n个指针形参。在这个函数中改变这n个形参的值;
③在主调函数中调用这个函数,在调用时将这n个指针变量作实参,将他们的值,也就是相关变量的地址传给该函数的形参;
④在执行该函数的过程中,通过形参指针变量,改变它们所指向的n个变量的值;
⑤主调函数中就可以使用这些改变了值的变量。
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
【例9.3】题目要求同例9.2,即对输入的两个整数a和b,按大小顺序输出。要求用函数处理,在该函数中使较大的值存放在a中,小的值存放在b中。
#include<stdio.h>
int main()
{
void swap(int *p1,int *p2); //对swap函数的声明
int a,b;
int *pointer_a,*pointer_b; //定义两个int*型的指针变量
printf("please enter two integer numbers:");
scanf("%d,%d",&a,&b); //输入两个整数
pointer_a=&a; //使pointer_1指向a
pointer_b=&b; //使pointer_1指向b
if(a<b)swap(pointer_a,pointer_b); //如果a<b,调用swap函数
printf("max=%d,min=%d\n",a,b); //输出结果
return 0;
}
void swap(int *p1,int *p2) //定义swap函数
{
int temp;
temp=*p1; //使*p1和*p2互换
*p1=*p2;
*p2=temp;
} //本例交换a和b的值,而p1和p2的值不变。这恰和例9.2相反
不能企图通过改变指针形参的值而使指针实参的值改变
【例9.4】输出3个整数a,b,c,要求按大小顺序将他们输出。定义一个函数,实现使这3个变量按值的大小排序。
#include<stdio.h>
int main()
{
<