c第7章教学zp.docx
《c第7章教学zp.docx》由会员分享,可在线阅读,更多相关《c第7章教学zp.docx(15页珍藏版)》请在冰豆网上搜索。
c第7章教学zp
第七章指针
7.1指针与地址的基本概念
一、地址
二、指针与指针变量
7.2变量的指针和指向变量的指针变量。
一.指针变量的定义
二、指针变量的引用
三、空指针
四、指针的运算
873指针与函数
一、函数参数为指针变量
二、函数返回地址值
第七章指针
7.1指针与地址的基本概念(P105)
一、地址
1.内存单元的地址
内存单元的基本单位是字节,为了方便对内存的访问,每一个内存单元都有一个编号,这个编号就称为内存单元的地址。
2.内存单元的内容
内存单元中存放的数据即是内存单元的内容。
例:
inti=9,j=6,k=5;
说明:
每当在程序中定义了变量,C编译系统就会根据变量的不同类型,在内存中为其分配相应字节数目的存储空间。
把变量在内存中所占存储单元的首地址,称为该变量的地址(Address)。
把变量在内存中所占存储单元中存放的数据,称为该变量的内容。
而在计算机内存中,对变量值的存取实质上是通过地址进行的。
例如:
printf(“%d”,i);
scanf(“%d”,&i);
例7.0观察地址
#include
voidmain()
{intx;
x=55;
printf("x=%d\n",x);
printf("xaddresis:
=%u\n",&x);
}
3.“直接访问”与“间接访问”
●按变量名存取变量值的方式称为“直接访问”。
●按变量地址的存放单元存取变量值的方式称为“间接访问”。
例如:
ii_pointeri
20002000
(1)(直接访问)
(2)(间接访问)
二、指针与指针变量(P106)
1.指针
一个变量的地址称为该变量的“指针“。
说明:
由于通过地址可以找到所需的变量单元,也即是说,地址“指向“该变量单元,因此,在C中,将地址形象化地称为”指针“。
如:
2000是变量i的指针。
2.指针变量
一种用来存放另一个变量地址值的特殊变量,其值是内存单元的地址。
如:
i_pointer
7.2变量的指针和指向变量的指针变量。
所谓变量的指针就是变量的地址,而指针变量是用来存放变量的地址。
i_pointeri
2000
在指针变量与他所指向的变量之间存在着一种联系。
用“*“表示指向,则:
*i_pointer=i
一.指针变量的定义(P106)
指针变量也是变量,他具有变量的所有特性。
如:
在内存中占据一定的存储空间,遵循“先定义,后使用”的原则等,但指针变量作为一种特殊的变量,他的内容只能是地址,而不能是数据。
1.指针变量定义的一般形式
类型标识符*指针变量名
例如:
int*pointer_1,*pointer_2;
float*pointer_3;
char*pointer_4;
2.说明
①“*“表示该变量为指针变量(在定义语句中);
②指针变量具有“基类型”,基类型不同的指针变量不能混合使用;
③指针变量在内存中所占的存储空间是一样的(此点与数据类型说明不同)。
例如:
int*pc;
char*px;
pc、px为两个指针变量,分别为指向整型变量和实型变量的指针,作为pc、px本身在内存中所占的存储空间都是一样的。
二、指针变量的赋值与引用(P106~109)
1.指针运算符
①&:
取地址运算符;
②*:
指针运算符(或称“间接访问“运算符)
说明:
①“&”其功能是求出运算量的地址,他要求运算量必须是变量,而不能是表达式、常量等。
例如:
intx=5,*p;
p=&x;
表示把变量x的地址赋给指针变量p(不改变x的值)。
假设,变量x的值为10,其在内存中的地址为3000,则执行上述语句后,p的值为:
3000
注意:
在给指针变量赋地址值时,必须要确保指针变量的基类型与所赋地址值中存放的变量保持类型一致。
例如:
int*p;
charch;
则语句:
p=&ch是错误的。
②“*”其功能与“&”相反,用于返回一个指针所指对象的内容。
他要求运算对象必须是已被正确初始化或已指向某一确定内存单元的指针变量。
例如:
int*p1,*p2,i=0,j=1;
p1=&i;p2=&j;
则j=*p1等价于j=i;(即j的值变为0)
i=*p1+3等价于i=i+3;
例7.1练习指针的使用
#include
main()
{inta=10,A;
floatb=20.1,B;
charc='c',C;
int*p1;
float*p2;
char*p3;
p1=&a;p2=&b;p3=&c;
A=*p1;B=*p2;C=*p3;
printf("\%d%f%c\n",A,B,C);
}
例7.2通过指针变量的修改来改变被指示变量的值。
#include
voidmain()
{inta=10,b;
int*p;
p=&a;
b=a;
printf("\nNowthea=%d,b=%d,*p=%d",a,b,*p);
*p+=10;
printf("\nNowthea=%d,b=%d,*p=%d",a,b,*p);
b+=10;
printf("\nNowthea=%d,b=%d,*p=%d",a,b,*p);
a=a+10;
printf("\nNowthea=%d,b=%d,*p=%d",a,b,*p);
}
例7.3对比指针变量值的改变与指针变量指向地址内容的改变。
#include
voidmain()
{inta=10,b=20,c=30,d=40;
int*p1=&a;
int*p2=&b;
int*p3=&c;
int*p4=&d;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
printf("\nNowc=%d,d=%d,*p3=%d,*p4=%d",c,d,*p3,*p4);
p1=p2;
*p3=*p4;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
printf("\nNowc=%d,d=%d,*p3=%d,*p4=%d",c,d,*p3,*p4);
}
例7.4通过指针变量交换两个变量的值(cex7_41,cex7_42)
/*ctex7_41*/
#include
voidmain()
{inta=10,b=20;
int*p1=&a;
int*p2=&b;
intt;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
{t=*p1;*p1=*p2;*p2=t;}
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
}
/*ctex7_42*/
#include
voidmain()
{inta=10,b=20;
int*p1=&a;
int*p2=&b;
int*t;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
{t=p1;p1=p2;p2=t;}
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
}
三、空指针(P107)
1.空指针的含义
所谓“空指针”是指:
指针变量不指向任何变量或数据。
一般而言,“空指针”在以下二种情况下出现:
①定义了一个指针变量,既没有进行初始化,也没有对其进行赋值;
②用一个宏定义NULL为其指针变量赋值。
2.良好的建议:
当定义了一个指针变量,但暂时又不马上使用时,可为他赋一个NULL值(即空值),以明确表示该指针变量目前不指向任何一个存储单元。
例如:
p=NULL;(p为指针变量)
注意:
①NULL是系统在stdio.h文件中定义的预定义标识符;
②NULL的拼写必须采用大写字母。
例7.5空指针的使用
#include
voidmain()
{inta=10,b=20;
int*p1=&a;
int*p2=&b;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
p1=NULL;
p2=NULL;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
p1=&b;
p2=&a;
printf("\nNowa=%d,b=%d,*p1=%d,*p2=%d",a,b,*p1,*p2);
}
说明:
在运行结果中看到的当p1与p2赋值为NULL时,其输出结果为均为0,此处的0并不表示p指向了地址为0的存储单元,而仅仅表示p不指向任何存储单元。
四、指针的运算
1.算术运算
当指针指向一串连续的存储单元时,可以对指针变量进行加、减一个整数的运算;对于指向同一连续存储单元的两个指针变量可以进行相减运算;除此之外,不可以对指针变量做任何其他算术运算。
例如:
设在内存中开辟了如图所示的5个连续的、存放整型数据的存储单元,且已经定义了指针变量p和q,并使p指向值为10的存储单元。
执行:
p=p+3;
执行:
q=p-2;
说明:
对指针变量进行加、减一个整数时,数字1并不代表一个字节,而是指向一个存储单元的长度。
至于一个存储单元的长度是多少字节,则视指针变量的基类型而定。
如:
p是int型,则1个单元长度是2个字节;
p是float型,则1个单元长度是4个字节;
p是double型,则1个单元长度是8个字节;等等。
2.比较运算
两个指针变量间进行比较,实质上就是两个地址间的比较。
如:
p==q;表明两个指针变量指向同一个变量。
通常情况下,只有当两个或多个指针变量指向同一连续存储空间时,指针变量间的比较操作才有意义。
7.3指针与函数(P109)
指针与函数有三种关系:
①指针可以作为函数参数,②函数的返回值可以是指针,③指针可以指向函数。
一、函数参数为指针变量(P109)
使用指针变量作为函数参数的主要目的之一是实现实参与形参按地址传递。
案例7.6利用指针变量实现形参与实参之间的数据传递。
#include
myadd(int*a,int*b)
{intsum;
sum=*a+*b;
returnsum;
}
main()
{intx,y,z;
printf("ENTERx,y:
");
scanf("%d,%d,%d",&x,&y);
z=myadd(&x,&y);
printf("%d+%d=%d\n",x,y,z);
}
案例7.7利用函数实现两个变量值的交换。
#include
voidswap(int*a,int*b)
{inttmp;
printf("A=%4dB=%4d\n",*a,*b);
tmp=*a;*a=*b;*b=tmp;
printf("A=%4dB=%4d\n",*a,*b);
}
voidmain()
{intx=20,y=-40;
printf("X=%4dY=%4d\n",x,y);
swap(&x,&y);
printf("X=%4dY=%4d\n",x,y);
}
案例7.8分析如下程序
#include
intchange(int*x)
{printf("\ninfunctionchange,xis%d",*x);
*x=*x+10;
printf("\nnowinfunctionchange,xis%d",*x);
return1;
}
voidmain()
{inty,*p;
intr;
y=10;
p=&y;
printf("\nfirst,inmaintheyis%d",y);
r=change(p);
printf("\nsecond,inmaintheyis%d",y);
r=change(&y);
printf("\nthird,inmaintheyis%d",y);
}
案例7.9对例7.7修改为如下程序,分析其运行结果。
#include
voidswap(int*a,int*b)
{int*tmp;
printf("A=%4dB=%4d\n",*a,*b);
tmp=a;a=b;b=tmp;
printf("A=%4dB=%4d\n",*a,*b);
}
voidmain()
{intx=20,y=-40;
printf("X=%4dY=%4d\n",x,y);
swap(&x,&y);
printf("X=%4dY=%4d\n",x,y);}
二、函数返回地址值(P112)
C函数值的类型既可以简单数据类型,还可以是指针类型。
定义返回指针函数的一般形式:
类型名*函数名(形参表)
{
函数体
}
调用返回指针的函数的赋值语句一般形式:
指针变量=函数名;
表示把函数的地址赋给指针变量,即指针变量指向函数。
案例7.10
#include
int*fun(int*a,int*b)
{if(*a>*b)returna;
returnb;
}
main()
{int*p,i,j;
printf("entertwonumber:
");
scanf("%d,%d",&i,&j);
p=fun(&i,&j);
printf("i=%d,j=%d,*p=%d\n",i,j,*p);
}
7.4指向函数的指针变量(P113)(*)
一、引入指向函数的指针变量的意义
C语言规定:
函数名代表该函数的首地址,因此可通过指向该函数的指针变量调用该函数
二、指向函数的指针变量的定义
类型名(*指针变量名)();
例如:
int(*p)();
表示p为指向返回值为int型函数的指针变量。
例7.11P113例7。
6用指向函数的指针调用函数的方法
#include
intmax(inta,intb)
{return((a>b)?
a:
b);
}
voidmain()
{int(*p)();//定义指向函数的指针变量
intx,y,z;
p=max;//p指向函数max
printf(“pleaseinputa&b:
”);
scanf(“%d,%d”,&a,&b);
z=(*p)(x,y);
printf(“max=%d”,z);
}