第9章 指针(汪同庆)_第1页
第9章 指针(汪同庆)_第2页
第9章 指针(汪同庆)_第3页
第9章 指针(汪同庆)_第4页
第9章 指针(汪同庆)_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

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

文档简介

第九章指针简介指针功能强大,不易掌握。用来模拟引用传递。与数组和字符串关系密切。可以创建和操作动态的数据结构:链表队列栈树指针2指针的概念指针就是内存对象的地址。内存对象包括:变量,数组,函数等。C语言允许直接通过地址来处理数据。指针intx;x=23;内存单元的地址一个无符号的整数,就是指向变量的指针。变量名其实就是内存单元的符号化名称。内存单元的内容就是变量的值。FF00x23直接引用Directreference通过变量名直接引用变量占用的内存单元。3内存对象的地址变量的地址用取地址运算符(&)获得变量在内存中的地址。数组的地址即第一个元素的地址,用数组名表示。函数的地址用函数名表示。指针intvar;scanf(“%d”,&var);vararrayfunctionintarray[3];intfunction(intx);4指针变量指针变量就是保存内存地址的变量。指针intx=23;int*x_pointer;x_pointer=&x;FF00x23FFF0x_pointerFF00指针变量保存变量的地址。变量x_pointer

的值是变量x的地址(指针)。目前,指针x_pointer

指向变量x。间接引用Indirectreference通过指针变量间接引用变量占用的内存单元。5指针变量指针变量的声明<类型说明符>*<指针变量名>;*表示x_pointer是一个指针变量x_pointer是int*类型的指针,读作:指向int型数据的指针指向整型对象的指针指针可以声明为指向任何数据类型的对象声明多个指针时,每个变量前都必须有*指针int*x_pointer;int*x_pointer,*y_pointer;char*charPtr;注意所有指针变量保存的数据的类型是相同的,即一个内存单元的地址,但是,它们指向的数据的类型可以不同。6指针变量指针变量的初始化在声明语句中为指针变量指定初值。指针变量可以被初始化为0,NULL或一个地址量。0和NULL是等价的(用NULL更好)NULL是在<stdio.h>(和几个其他头文件)中定义的符号常量指针intx,*p=&x;intx,*p=0xffe;intx,*p=(int*)0xffe;强制类型转换intx,*p=NULL;空指针:不指向任何对象Warning:Nonportablepointerconversion7取地址运算符取地址运算符:&返回变量在内存中的地址。指针inty,*yPtr;y=5;yPtr=&y;5yPtrfff0yff00yPtry5y的地址是yPtr的值yPtr“指向”yff008指针运算符指针运算符:*返回指针变量所指向的对象的别名。*yPtr就是y,因为yPtr指向y。可以用在赋值语句中。指针inty=5,*yPtr;yPtr=&y;inty,*yPtr;yPtr=&y;*yPtr=5;9案例分析:指针运算符指针运算符指针#include<stdio.h>voidmain(){inta,*aPtr;a=7;

aPtr=&a;printf("Theaddressofais%p"

"\nThevalueofaPtris%p",&a,aPtr);printf("\n\nThevalueofais%d"

"\nThevalueof*aPtris%d",a,*aPtr);printf("\n\nShowingthat*and&areinversesofeachother."

"\n&*aPtr=%p"

"\n*&aPtr=%p",&*aPtr,*&aPtr);}10案例分析:指针运算符指针运算符运行结果指针Theaddressofais1A58ThevalueofaPtris1A58Thevalueofais7Thevalueof*aPtris7Showingthat*and&areinversesofeachother.&*aPtr=1A58*&aPtr=1A58*和&是互反的11指针作为函数的参数指针作为函数的参数用来模拟引用传递。用指针变量作为函数的形式参数。调用函数时,用&运算符把实际参数的地址传递给函数。在被调用函数中,用*运算符间接引用实际参数。指针intmyFunc(int

*ptr);myFunc(&var);intmyFunc(int*ptr){

*ptr=…}12案例分析:指针参数问题:计算任意整数的立方。值传递:callByValue()指针#include<stdio.h>intcallByValue(int);/*返回参数的立方*/voidmain(){intnumber=5;printf("Theoriginalvalueofnumberis%d",number);

number=callByValue(number);printf("\nThenewvalueofnumberis%d",number);}intcallByValue(intn){

returnn*n*n;}Theoriginalvalueofnumberis5Thenewvalueofnumberis12513案例分析:指针参数问题:计算任意整数的立方。值传递:callByReference()指针#include<stdio.h>voidcallByReference(int*);voidmain(){intnumber=5;printf("Theoriginalvalueofnumberis%d",number);

callByReference(&number);printf("\nThenewvalueofnumberis%d",number);}voidcallByReference(int*nPtr){

*nPtr

=

*nPtr**nPtr**nPtr;}Theoriginalvalueofnumberis5Thenewvalueofnumberis12514案例分析:指针参数问题:计算任意整数的立方。结果分析指针voidmain(){intnumber=5;callByReference(&number);}voidcallByReference(int*nPtr){*nPtr=*nPtr**nPtr**nPtr;}voidmain(){intnumber=5;callByReference(&number);}voidcallByReference(int*nPtr){*nPtr=*nPtr**nPtr**nPtr;}voidmain(){intnumber=5;callByReference(&number);}voidcallByReference(int*nPtr){*nPtr=*nPtr**nPtr**nPtr;}nPtr5numbernPtr125numbernPtr125number调用前调用时调用后15案例分析:指针参数问题:交换两个变量的值。哪一种实现是正确的?指针voidswap(intx,inty){inttmp;tmp=x;x=y;y=tmp;}voidmain(){inta=4,b=6;swap(a,b);printf("a=%d,b=%d",a,b);}a=4,b=6voidswap(int*x,int*y){inttmp;tmp=*x;*x=*y;*y=tmp;}voidmain(){inta=4,b=6;swap(&a,&b);printf("a=%d,b=%d",a,b);}a=6,b=416指针运算指针可以参与以下运算:赋值运算给指针变量赋值关系运算两个指针之间的比较算术运算加(减)一个整数两个指针相减指针17指针运算指针的赋值运算可以把指针赋给同类型的指针变量。指针intx=10,*p,*q;p=&x;q=p;printf(“*q=%d",*q);*q=1010x2000p2000q200018指针运算指针的赋值运算把指针赋值给类型不同的指针变量时要进行类型转换。但void*类型的指针是一个例外。指针inta,*intPtr=&a;char*charPtr;charPtr=(char*)intPtr;inta,*intPtr=&a;char*charPtr;void*voidPtr;voidPtr=intPtr;charPtr=voidPtr;void*通用指针代表任何指针类型不能间接引用19指针运算指针的赋值运算比较两个指针的值。指针p1<p2p1<=p2p1>p2p1>=p2p1==p2p1!=p22000p12002p2char*charPtr;…charPtr>=(char*)2000与同类型的指针常量比较常常与0比较20指针运算指针的算术运算自增自减(++,--)加上一个整数(+,+=,-,-=)两个指针相减指针21指针运算指针的算术运算举例指针int*vP1,*vP2;vP1=(int*)2000;vP2=vP1+2;2000200220042006数组vvP12000+2=20022000+2*2=2004vP2所指向的内存对象的长度?vP1+222指针运算指针的算术运算举例指针int*vP1,*vP2;vP1=(int*)2000;vP2=(int*)2004;2000200220042006数组vvP1vP2vP2和vP1之间内存对象的个数?vP2-vP1

=2指针的算术运算在数组上使用才有意义23指针与数组数组和指针关系密切。数组名是一个指针常量。数组指针:指向数组的指针。数组指针可以用来完成任何涉及数组下标的操作。将bPtr的值置为数组b中的第一个元素的地址 bPtr=b;等价于

bPtr=&b[0];指针intb[5];int*bPtr;24指针与数组数组和指针关系密切。引用数组元素的表达式数组元素b[3]可以用*(bPtr+3)来引用3是偏移量这种表示法称为指针偏移量表示法还可以用bPtr[3]来引用称为指针下标表示法与b[3]相同还可以用*(b+3)来引用指针25指针与数组数组和指针关系密切。引用数组元素的表达式指针main(){inti,a[5]={1,2,3,4,5};for(i=0;i<5;i++)printf("%2d",a[i]);}下标法main(){inti,a[5]={1,2,3,4,5};for(i=0;i<5;i++)printf("%2d",*(a+i));}地址法main(){inta[5]={1,2,3,4,5},*p;for(p=a;p<(a+5);p++)printf("%2d",*p);}指针法26指针与数组数组和指针互换使用时的注意事项数组名是一个指针常量。指针因为a是数组名,即数组的首地址,它的值在程序运行期间是固定不变的!是一个常量。错main(){inta[5]={1,2,3,4,5},*p;for(p=a;a<(p+5);a++)printf("%2d",*a);}27指针与数组数组和指针互换使用时的注意事项注意指针变量的值。指针要注意指针变量的当前值。ppa[0]a[1]a[2]a[3]a[4]数组amain(){inti,a[5],*p;p=a;for(i=0;i<5;i++)scanf("%d",p++);for(i=0;i<5;i++,p++)printf("%d",*p);}错p=a;28指针与数组数组和指针互换使用时的注意事项注意运算符的优先级。指针*aPtr++*(aPtr++)等价考虑:*++aPtr与*(++aPtr)inta=0,*aPtr=&a;printf("a=%d,aPtr=%p\n",a,aPtr);printf("%d\n",*aPtr++);printf("a=%d,aPtr=%p\n",a,aPtr);a=0,aPtr=1BCC0a=0,aPtr=1BCE29指针与数组数组参数的值传递形参数组是一个指针变量。指针voidsort(int*x,intn){…}voidmain(){inta[10];……sort(a,10);…}a,xa[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]地址voidsort(intx[],intn){…}等价30指针数组数组元素是指针的数组<类型说明符>*<数组名>[<常量表达式>];常用来构造字符串数组。注意:字符串并不在suit数组中。suit数组只包含指向字符串的指针。指针char*suit[4]

={“Hearts”,“Diamonds”,“Clubs”,“Spades”};suit[3]suit[2]suit[1]suit[0]’H’’e’’a’’r’’t’’s’’\0’’D’’i’’a’’m’’o’’n’’d’’s’’\0’’C’’l’’u’’b’’s’’\0’’S’’p’’a’’d’’e’’s’’\0’suit的长度是固定的,但却可以访问任意长度的字符串31案例分析:指针数组问题:洗牌和发牌的模拟定义数据结构字符串(指针)数组suit保存牌的花色名字符串(指针)数组face保存牌的号码二维数组deck表示一副牌,行对应花色,列对应号码保存洗牌后牌的序号指针deck[

2

][

12

]representstheKingofClubsHeartsDiamondsClubsSpades0123AceTwoThreeFourFiveSixSevenEightNineTenJackQueenKing0123456789101112ClubsKing32案例分析:指针数组问题:洗牌和发牌的模拟设计算法算法的顶部第一次细化指针对52张牌进行洗牌和发牌初始化suit数组初始化face数组初始化deck数组对52张牌洗牌对52张牌发牌33案例分析:指针数组问题:洗牌和发牌的模拟设计算法第二次细化指针初始化suit数组初始化face数组初始化deck数组对52张牌中的每张在随机选择的纸牌空位上放置纸牌序号对52张牌中的每张查找deck数组中纸牌的序号,并显示纸牌的花色和号码34案例分析:指针数组问题:洗牌和发牌的模拟设计算法第三次细化指针初始化suit数组初始化face数组初始化deck数组对52张牌中的每张随机选择纸牌位置当所选纸牌位置已经被选过(有序号)随机选择纸牌位置在所选纸牌位置中放置纸牌序号对52张牌中的每张对于deck数组的每个位置如果该位置包含期望的纸牌序号显示纸牌的花色和号码35案例分析:指针数组问题:洗牌和发牌的模拟源代码指针#include<stdio.h>#include<stdlib.h>#include<time.h>voidshuffle(int[][13]);voiddeal(int[][13],char*[],char*[]);voidmain(){char*suit[]={"Hearts","Diamonds","Clubs","Spades"};char*face[]={"Ace","Two","Three",

温馨提示

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

评论

0/150

提交评论