C语言指针学习 谭浩强版_第1页
C语言指针学习 谭浩强版_第2页
C语言指针学习 谭浩强版_第3页
C语言指针学习 谭浩强版_第4页
C语言指针学习 谭浩强版_第5页
已阅读5页,还剩87页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第8章 善于利用指针,8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串,1.变量的“直接访问”方式:,3,直接访问:,按变量的地址(即变量名)存取变量值的方式。,例如: int i=3;,讨论一个问题:,A、B和C三人约定住宿在某旅馆。A先到达旅馆,在服务台登记了房间,房间号是2010。然后,A电话通知了B,但没有通知C。,B怎样找到A呢?,B可以直接到2010找到A.,int i=3,j=6,k;,printf(“%d”,i);,通过变量名i,找到i的地址2000H,从而从存储单元读取3,讨论一个问题: A、B和C三人约定住宿在某旅馆。A先到达旅馆,

2、在服务台登记了房间,房间号是2010。然后,A电话通知了B,但没有通知C。,C怎样找到A呢?,C可以从旅馆的服务台查询到A的房号2010,间接找到A。,将变量的地址放在另一个内存单元中,先到另一个内存单元中取得变量的地址,再由变量的地址找到变量并进行数据存取(见下图)。,2.变量的“间接访问”方式,间接访问方式:,3,作用相当 服务台,int i=3,j=6,k;,定义特殊变量i_pointer,将i的地址存到这里,间接存取,i_pointer=,*i_pointer=50;,50,8.1 指针是什么,地址: 内存中存储单元的编号。 指针:在C在语言中一个变量的地址称为该变量的“指针”。 例如

3、: int a; /* int *p1, *p2; p1= ,8.2.1 使用指针变量的例子,p1 如:int *p1, *p2; int是为指针变量指定的“基类型”。 基类型指定指针变量可指向的变量类型。 p1,p2是指针变量名,而不是*p1,*p2 如p1可以指向整型变量,但不能指向浮点型变量。,例如:int a ; float b ; int *p; p = ,正确,错误,8.2.3 怎样引用指针变量,在引用指针变量时,可能有三种情况: 给指针变量赋值。如:p=,使p指向a,*p相当于a,以十六进制输出a的地址,8.2.3 怎样引用指针变量,要熟练掌握两个有关的运算符:,1、 /*将m的

4、地址赋给指针变量p*/,8.2.3 怎样引用指针变量,要熟练掌握两个有关的运算符:,2、* 间接存取运算 功能:返回其后随地址(指针变量值)中的变量值 例:int *p ,m ; p= /*将200赋给指针变量p所指向的变量m*/,指针变量的赋值: 变量的指针(地址)是一个无符号整数,可以将一个变量的指针赋值给一个指针变量,但不能将一个整数直接赋值给一个指针变量。 1、用变量的地址给指针变量赋值(求地址运算符 注意:指针变量若不赋值,则指针变量的值是随机的。,危险,8.2.3 怎样引用指针变量,例 main( ) int i=10,b=3; int *p; *p=i; printf(“%d”,

5、*p); ,危险!,例 main( ) int i=10,k; int *p; p= ,指针变量必须先赋值,再使用,10,(2)指针变量不赋值,指针变量的值是随机的,指向也是随机的,具有不确定性;,3、赋空值NULL,例如:,int *p ; p =NULL ;,或p 0 ;,指针变量赋空值NULL与不赋值的区别:,(1)指针变量赋空值NULL,指向为0的单元,系统保证该单元不作它用,表示指针变量值没有意义;,用途:避免指针变量的非法引用,在程序中常作为状态比较,4、void *类型指针,void *p;,表示不指定p是指向哪一种类型数据的指针变量,使用时要进行强制类型转换,取指针变量所指向地

6、址内容:,b = * p ;,存指针变量所指向地址内容:,* p 50 ;,例如: main() int a = 5 , b = 3 , *p ; p = ,*p,2000,3,5,运行结果:,a = 4 , b = 8,8,4,注意:,*p若出现在“”的右边或其他表达式中则为取内容,*p若出现在“”的左边则为存内容,例8.2 输入a和b两个整数,按先大后小的顺序输出a和b。 #include int main() int *p1,*p2,*p,a,b; printf(please enter two integer numbers:); scanf(%d,%d, ,#include void

7、 main() int a = 5 , b = 8 ; int t ; printf(“a= %d , b = %dn” ,a ,b); t = a ; a = b ; b = t ; printf(“a= %d , b = %dn” ,a ,b); ,#include void main() int a = 5 , b = 8 ; int *pa = ,例题1:交换a,b两个数,直接访问,间接访问,例题2:编写一个函数实现两个数的交换,#include void swap( int x , int y ) int t ; t = x ; x = y ; y = t ; void main()

8、 int a = 3 , b = 5 ; swap( a , b ) ; printf(“a = %d , b = %d n” , a , b ); ,5,a,2010H,b,2B12H,x,3100H,y,3F02H,3,5,3,3 5,5 3,3,t,4D24H,不能实现两个数的交换,参数之间是值传递,单向(从实参传递给形参),例题3: #include void swap( int *x , int *y ) int t ; t = *y ; *y = *x ; *x = t ; void main() int a = 3 , b = 5 ; swap( ,5,a,2010H,b,2B1

9、2H,x,3100H,y,3F02H,2010,2B12,3,3,3 5,t,4A10H,5,能实现两个数的交换,8.2.4 指针变量作为函数参数,例题3: #include void swap( int *x , int *y ) int t ; t = *y ; *y = *x ; *x = t ; void main() int a = 3 , b = 5 ; swap( ,5,a,2010,b,2B12,3,3,3 5,c语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作函数参数也要遵循这一规则。调用函数不可能改变实参指针变量的值,但是可以改变实参指针变量所指变量

10、的值。,例题4: #include void swap( int *x , int *y ) int *t ; t = x ; x = y ; y = t ; void main() int a = 3 , b = 5 ; swap( ,5,a,2010,b,2B12,x,3100,y,3F02,2010,2B12,3,2B12,2010,t,4C00,2010,不能实现两个数的交换,1.实参和形参都是指针变量,2.被调函数中修改指针所指向的空间的值(即修改*p的值),指针作为参数,地址传递的条件:,void swap( int *x , int *y ) int t ; t = *y ; *

11、y = *x ; *x = t ; ,void swap( int *x , int *y ) int *t ; t = x ; x = y ; y = t ; ,void main() int a = 3 , b = 5 ; swap( ,/能实现交换功能的函数,/不能实现交换功能的函数,#include void swap( int *x , int *y ) int *t ; *t = *x ; *x = *y ; *y = *t ; void main() int a = 3 , b = 5 ; swap( ,有问题:指针变量t没有指向对象,语句存在危险,#include void s

12、wap( int *x , int *y ) int *t , w ; t = ,能够实现两个数的交换,例如: int a , *pa ; pa = ,指针变量说明表格,要求:”*”后面必须是地址表达式 , 数组a中下标为i(假设i的取值合理)的数组元素的地址:, int *p; p=,注意: 数组名a是数组首元素的地址,是一级指针。 “p=a;”的作用是“把a数组的首元素的地址赋给指针变量p” 。 即 p 下标法对数组进行运算 for(i=0;i32;i+) scanf(“%d”,例:int a10,*p ; p= 计算:+p 表达式值为 假设a0的地址为2000,则 p的值为2000 p+

13、1的值为2004 P-1的值为1996,越界,(2) 如果p的初值为指针与整型常量或整型变量的比较无意义,唯整数 0 例外( 0 表示空指针)。,例:有定义:double a5,*p1,*p2 ;p1,p2指向如图所示,p1=NULL 或 p1=0 或 !p1 判断p1是否为空指针 结果:0,a,a0,a1,a2,a3,a4,p1,p2,计算: p1= =p2 判断p1,p2是否指向同一变量 结果:0,p1p2 指向前面元素的指针变量地址值小 结果:1,p1!=0 或 p1 功能同上,结果相反 结果:1,低地址,高地址,第i个元素地址的表示(p的初值为a) : a+i 数组名法 p+i 指针法

14、 p+;p=p+5; a=,总结,正确,错误,设 int a5 , *p = a ;,指针变量,数组指针,下标法,地址关系:,p a ,指针法,数组名,下标法,*( p) *( a) a 0 p 0 ,*(p + 1) *( a + 1) a 1 p 1 ,*(p + 2) *(a + 2) a 2 p2,*( p + 3) *( a + 3) a 3 p3,*(p + 4) *( a + 4) a 4 p4,下标法,8.3.3 通过指针引用数组元素,引用一个数组元素,可用下面两种方法: 其中a是数组名,p是指向数组元素的指针变量,其初值p=a。 () 下标法 如ai、pi形式 () 指针法

15、如*(a+i)或*(p+i),8.3.3 通过指针引用数组元素,例8.6 有一个整型数组a,有10个元素,要求输出数组中的全部元素。 解题思路:引用数组中各元素的值有3种方法: (1)下标法; (2)通过数组名计算数组元素地址,找出元素的值; (3) 用指针变量指向数组元素,(1) 下标法。 #include int main() int a10; int i; int *p = a ; printf(please enter 10 integer numbers:); for(i=0;i10;i+) scanf(%d, ,下标法,for(i=0;i10;i+) printf(%d ,pi )

16、;,(2) 通过数组名计算数组元素地址,找出元素的值 #include int main() int a10; int i; int *p = a ; printf(please enter 10 integer numbers:); for(i=0;i10;i+) scanf(%d, ,指针法,for(i=0;i10;i+) printf(%d ,*(p+i) );,(3) 用指针变量指向数组元素 #include int main() int a10; int *p,i; printf(please enter 10 integer numbers:); for(i=0;i10;i+) s

17、canf(%d, ,for(i=0;i10;a+,i+) printf(“%d ”,*a);,错! 数组名是常量,不可以修改值,指针变量法,例8.7 通过指针变量输出整型数组a的10个元素。 #include int main() int *p,i,a10; p=a; printf(“enter 10 integer numbers:n); for(i=0;i10;i+) scanf(“%d”,p+); p=a; for(i=0;i10;i+,p+) printf(“%d ”,*p); printf(n); return 0; ,是否可以省略?,8.3.4 用数组名作函数参数,用数组名作函数参

18、数时,因为实参数组名代表该数组首元素的地址,形参应该是一个指针变量。 C编译都是将形参数组名作为指针变量来处理的。,void fun(int arr,int n); int main() int array10; fun (array,10); return 0; void fun(int arr ,int n) ,void fun(int *arr,int n),array0,arr0,array数组,arr,array3,arr3,arr+3,*arr,例8.8 将数组a中n个整数按相反顺序存放 解题思路:将a0与an-1对换,将a4与a5对换。,j,i,2,3,j,i,5,9,j,i,4

19、,7,j,i,7,11,j,i,6,0,例8.8 将数组a中n个整数按相反顺序存放 #include void inv(int x ,int n); int main() int i, a10=3,7,9,11,0,6,7,5,4,2; for(i=0;i10;i+) printf(“%d ”,ai); printf(n); inv(a,10); for(i=0;i10;i+) printf(“%d ”,ai); printf(n); return 0; ,void inv(int x ,int n) int temp,i,j,m=(n-1)/2; for(i=0;i=m;i+) j=n-1-

20、i; temp=xi;xi=xj;xj=temp; ,void inv(int x ,int n) int temp,*i,*j; for(i=x, j=x+n-1; ij; i+,j-) temp=*i; *i=*j; *j=temp; ,例8.9 改写例8.8,用指针变量作实参。 #include void inv(int *x,int n); int main() int arr10,*p; for(p=arr;parr+10;p+) scanf(“%d”,p); p=arr; inv(p,10); for(p=arr;parr+10;p+) printf(“%d ”,*p); prin

21、tf(n); return 0; ,例8.10 用指针方法对10个整数按由大到小顺序排序。 #include void sort(int x ,int n); int main() int i,*p,a10; p=a; for(i=0;i10;i+) scanf(“%d”,p+); p=a; sort(p,10); for(p=a;pa+10;p+) printf(“%d ”,*p); printf(n); return 0; ,void sort(int x,int n) int i,j,k,t; for(i=0;ixk) k=j; if(k!=i) t=xi;xi=xk;xk=t; ,vo

22、id sort(int *x,int n),if (*(x+j)*(x+k) k=j;,t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;,在xix9中,最大数xk与xi对换,总结: 一级指针变量与一维数组的关系,int *p 与 int a10,1.数组名a是指针(地址)常量,2.p=a; p+i ,a + i 是ai的地址(,a0,a1,a2等价于一维数组名 1、 各行第0个元素的地址, 即,a: 行指针 a+i :移动i行,为i行行地址,ai: 元素指针, 为i行第0个(0列) 元素地址 int *p; for( p=a0 ;pa0+12 ;p+) if(p-a0 )%4=

23、0) printf(n); printf(%4d,*p); printf(n); return 0; ,注意数据类型的一致, 不能写为p=a;,元素指针p的 移动范围,指针变量小结,一级指针 (1)一级指针定义 int a , b10 , * p;,(2)一级指针定义赋值,p = ,p = ,若p=b;,/ 请给出数组b下标为5数组元素值表达式,/ p 指向a变量,/ p 指向b3数组元素,或 p = b + 3 ;,(3)规则,定义标识符时,若标识符两侧运算符*+=1,引用一级指针时,,该标识符是一级指针,引用的是指向的地址,若标识符两侧运算符*+=0,引用的是指向地址中值,若标识符两侧运算

24、符*+=1,注意:以上总结仅限于标识符两侧仅有*,两个运算符,若p=b;,/ 请给出数组b下标为5数组元素值表达式,p5,b5,*(p+5),*(b+5),指针变量小结,二级指针 (1)二级指针 int c310;,(2)引用,定义标识符时,若标识符两侧运算符 *+=2 , 标识符是二维指针,c,二维数组首地址,0,二级指针,c+i,第i行首地址,0,二级指针,ci+j,第i行j列元素地址,1,一级指针,cij,第i行j列元素值,2,值,注意:以上总结仅限于标识符两侧仅有*,两个运算符,指针变量小结,二级指针 (1)二级指针 int c310 ,*pc , *p;,(2)赋值,定义标识符时,若

25、标识符两侧运算符 *+=2 , 标识符c,pc是二维指针,注意:以上总结仅限于标识符两侧仅有*,两个运算符s,/ pc 指向c数组,pc = c ;,pc,二维数组首地址,0,二级指针,pc+i,第i行首地址,0,二级指针,pci+j,第i行j列元素地址,1,一级指针,pcij,第i行j列元素值,2,值,p如何赋值,8.4 通过指针引用字符串,8.4.1 字符串的引用方式 8.4.2 字符指针作函数参数 8.4.3 使用字符指针变量和字符数组的比较,8.4.1 字符串的引用方式,(1) 可以通过字符指针引用存放在数组中的字符串。 (2) 可以通过字符指针变量引用字符串常量。,例8.16 定义一

26、个字符数组,在其中存放字符串“I love China!”,输出该字符串和第8个字符。 #include int main() char string=I love China!; printf(%sn,string); printf(%cn,string7); return 0; ,例8.17 通过字符指针变量输出一个字符串常量。 #include int main() char *string=I love China!; printf(%sn,string); return 0; ,char *string; string=” I love China!”;,例8.18 将字符串a复制为

27、字符串b,然后输出字符串b。 #include int main() char a =I am a student.,b20; int i; for(i=0;ai!=0;i+) bi=ai; bi=0; printf(string a is:%sn,a); printf(string b is:); for(i=0;bi!=0;i+) printf(%c,bi); printf(n); return 0; ,例8.18 将字符串a复制为字符串b,然后输出字符串b。 #include int main() char a =I am a student.,b20; int i; for(i=0;*

28、(a+i)!=0;i+) *(b+i)=*(a+i); *(b+i)=0; printf(string a is:%sn,a); printf(string b is:); for(i=0;bi!=0;i+) printf(%c,bi); printf(n); return 0; ,例8.19 用指针变量来处理例8.18问题。 #include int main() char a=I am a boy.,b20,*p1,*p2; for(p1=a;p2=b;*p1!=0;p1+,p2+) *p2=*p1; *p2=0; printf(string a is:%sn,a); printf(str

29、ing b is:%sn,b); return 0; ,8.4.2 字符指针作函数参数,如果想把一个字符串从一个函数“传递”到另一个函数,可以用指针实现。 将一个字符串从一个函数传递到另一个函数,可以使用传地址的方式,即用字符数组名或字符指针变量作参数。有以下四种情况:,实参 形参 1 数组名 数组名 2 数组名 字符指针变量 3 字符指针变量 字符指针变量 4 字符指针变量 数组名,例8.20 用函数调用实现字符串的复制。 (1) 用字符数组名作为函数参数 #include void copy_string(char from,char to); int main() char a=I am

30、 a teacher.; char b=you are a student.; printf(“a=%snb=%sn,a,b); printf(copy string a to string b:n); copy_string(a,b); printf(“a=%snb=%sn,a,b); return 0; ,实参是数组名,void copy_string(char from, char to) int i; i = 0; while(fromi!=0) toi=fromi; i+; toi=0; ,形参是数组,填写代码: 实现字符串复制,(2)用字符型指针变量作实参 #include voi

31、d copy_string(char from, char to); int main() char a=“I am a teacher.”; char b=“you are a student.”; char *from=a,*to=b; printf(“a=%snb=%sn,a,b); printf(ncopy string a to string b:n); copy_string(from,to); printf(“a=%snb=%sn,a,b); return 0; ,实参是指针,(3)用字符指针变量作形参和实参 #include void copy_string(char *fro

32、m, char *to); int main() char *a=“I am a teacher.”; char b=“You are a student.”; char *p=b; printf(“a=%snb=%sn”,a,b); printf(ncopy string a to string b:n); copy_string(a,p); printf(“a=%snb=%sn”,a,b); return 0; ,实参是数组名,指针,void copy_string(char *from, char *to) for( ;*from!=0; from+,to+) *to=*from; *to=0; ,形参是指针变量,8.4.3 使用字符指针变量和字符数组的比较,注意字符数组与字符指针变量的区别。 (1) 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),并不是将字符串存放在字符指针变量中。 (2) 可以对字符指针变量赋值,但不能对数组名赋值。 cha

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论