您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 工作计划 > C语言教程同步课件12讲(第9章)
《C语言程序设计教程》编写组2007年1月第十二讲指针2第十二讲指针指针的概念指针变量的定义和初始化指针运算符指针作为函数参数指针与数组指针与字符串程序设计举例C语言程序设计3简介指针功能强大,不易掌握。用来模拟引用传递。与数组和字符串关系密切。可以创建和操作动态的数据结构:链表队列栈树指针4指针的概念内存单元地址称为指针。对内存单元的访问有直接和间接访问两种方式。C语言允许直接通过地址来处理数据。指针intx;x=23;内存单元的地址一个无符号的整数,就是指向变量的指针。变量名其实就是内存单元的符号化名称。内存单元的内容就是变量的值。FF00x23直接引用Directreference直接根据变量名存取变量的值。5内存对象的地址变量的地址用取地址运算符(&)获得变量在内存中的地址。数组的地址即第一个元素的地址,用数组名表示。函数的地址用函数名表示。指针intvar;scanf(“%d”,&var);vararrayfunctionintarray[3];intfunction(intx);6指针变量指针变量就是保存内存地址的变量。指针intx=23;int*x_pointer;x_pointer=&x;FF00x23FFF0x_pointerFF00指针变量•保存变量的地址。•变量x_pointer的值是变量x的地址(指针)。•目前,指针x_pointer指向变量x。间接引用Indirectreference将变量的地址存放在另一个内存单元中,当要对变量进行存取时先读取另一个内存单元的值,得到要存取变量的地址,再对该变量进行访问。7指针变量指针变量的声明类型说明符*指针变量名;*表示x_pointer是一个指针变量x_pointer是int*类型的指针,读作:–指向int型数据的指针–指向整型对象的指针指针可以声明为指向任何数据类型的对象声明多个指针时,每个变量前都必须有*指针int*x_pointer;int*x_pointer,*y_pointer;char*charPtr;注意所有指针变量保存的数据的类型是相同的,即一个内存单元的地址,但是,它们指向的数据的类型可以不同。8指针变量指针变量的初始化在声明语句中为指针变量指定初值。指针变量可以被初始化为0,NULL或一个地址量。–0和NULL是等价的(用NULL更好)–NULL是在stdio.h(和几个其他头文件)中定义的符号常量指针intx,*p=&x;intx,*p=NULL;空指针:不指向任何对象注意:任何指针在使用之前要进行定义并初始化,未经初始化的指针变量禁止使用。9取地址运算符取地址运算符:&返回变量在内存中的地址。&只能用于一个具体的变量或数组元素而不能是表达式或常量。指针inti,*ptr1;charch,*ptr2;ptr1=&i;/*将变量i的地址赋给指针变量ptr1*/ptr2=&ch;/*将变量ch的地址赋给指针变量ptr2*/下列运算是非法的:ptr1=&68;ptr1=&(i+1);因为&只能用于变量而不能用于常量或表达式。10指针运算符指针运算符:*能间接地存取指针所指向的变量的值。指针ptr1=&i;*ptr1=100;/*把100存入ptr1所指的地址(&i)中*/等同于i=100;又如:ptr2=&ch;*ptr2+=32;/*把ptr2所指向的地址(&ch)中的值加32*/相当于:ch+=32;ch=*ptr1;相当于:ch=i;11案例分析:指针运算符指针运算符指针#includestdio.hvoidmain(){inta=50,*p;p=&a;printf(“*p=%d\n”,*p);*p=100;printf(“a=%d\n”,a);}运行结果为:*p=50a=100*和&是互反的&取得一个东西的地址*得到一个地址里放的东西12指针作为函数的参数指针作为函数的参数用来模拟引用传递。用指针变量作为函数的形式参数。调用函数时,用&运算符把实际参数的地址传递给函数。在被调用函数中,用*运算符间接引用实际参数。指针intmyFunc(int*ptr);myFunc(&var);intmyFunc(int*ptr){*ptr=…}13案例分析:指针参数问题:交换两个变量的值。哪一种实现是正确的?指针voidswap(intx,inty){inttmp;tmp=x;x=y;y=tmp;printf(“x=%d,y=%d\n”,x,y);}voidmain(){inta=4,b=6;swap(a,b);printf(a=%d,b=%d,a,b);}voidswap(int*x,int*y){inttmp;tmp=*x;*x=*y;*y=tmp;printf(“*x=%d,*y=%d\n”,*x,*y);}voidmain(){inta=4,b=6;swap(&a,&b);printf(a=%d,b=%d,a,b);}x=6,y=4a=4,b=6*x=6,*y=4a=6,b=4案例分析:指针参数使用指针交换两个元素的值12-2.cvoidswap(int*x,int*y){int*temp;temp=x;x=y;y=temp;printf(“*x=%d,*y=%d\n”,*x,*y);}voidmain(){inta=4,b=6;swap(&a,&b);printf(“a=%d,b=%d\n”,a,b);}*x=6,*y=4a=4,b=6案例分析:指针参数使用指针交换两个元素的值12-1.cvoidswap(int*x,int*y){int*temp=x;*temp=*x;*x=*y;*y=*temp;printf(“*x=%d,*y=%d\n”,*x,*y);}voidmain(){inta=4,b=6;swap(&a,&b);printf(“a=%d,b=%d\n”,a,b);}*x=6,*y=6a=6,b=6案例分析:指针参数分析下列程序的输出结果。12-3.c#includestdio.hvoidfun(doublea,double*b,double*c){*b+=a;*c-=a;}voidmain(){doublex=15.3,y=10.6;fun(x-y,&x,&y);printf(%.1f,%.1f\n,x,y);}17指针与数组一个变量有一个地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。数组和指针关系密切。数组名是一个指针常量。数组指针:指向数组的指针(指向数组的起始地址),数组元素的指针是数组元素的地址。数组指针可以用来完成任何涉及数组下标的操作。将bPtr的值置为数组b中的第一个元素的地址bPtr=b;等价于bPtr=&b[0];指针intb[5];int*bPtr;18指针运算指针可以参与以下运算:赋值运算给指针变量赋值关系运算两个指针之间的比较算术运算加(减)一个整数两个指针相减指针19指针运算指针的赋值运算可以把指针赋给同类型的指针变量。指针intx=10,*p,*q;p=&x;q=p;printf(“*q=%d,*q);*q=1010x2000p2000q2000指针运算指针的赋值运算把数组的首地址赋予指向数组的指针变量。inta[5],*pa;pa=a;/*数组名表示数组的首地址,故可以赋予指向数组的指针变量pa*/也可写为:pa=&a[0];也可采取初始化赋值的方法:inta[5],*pa=a;指针运算指针的赋值运算把字符串的首地址赋予指向字符类型的指针变量。char*pc;pc=“CLanguage”;或:char*pc=“CLanguage”;说明:并不是将整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量。(在后面的章节有详细介绍)22指针运算指针的算术运算自增自减(++,--)加上一个整数(+,+=,-,-=)两个指针相减指针的算术运算在数组上使用才有意义。指针指针运算指针变量加(减)一个整数intm[12],*p1=&m[6],*p2=&m[8],*p3;p1=p1-3;p2--;p3=p2+2;指针运算移动指针变量访问数组元素。12-5.c#includestdio.hvoidmain(){intarray[10]={0,1,2,3,4,5,6,7,8,9},i;int*p=&array[0];for(i=0;i10;i++){printf(%d\n,*p);p++;}}25指针运算两个指针变量相减指针相减操作,一般只有高地址指针减低地址指针才有意义。指针voidmain(){inta[10]=(1,3,5,7,9,11,13,15,17,19};int*p1=&a[0],*p2=&a[9],t;while(p2-p10){t=*p1;*p1=*p2;*p2=t;p1++;p2--;}for(t=0;t10;t++)printf(“a[%d]=%d\n”,t,a[t]);}26指针运算指针的关系运算比较两个指针的值。指针p1p2p1=p2p1p2p1=p2p1==p2p1!=p22000p12002p2指针变量的比较运算经常用于数组,判定两个指针变量所指向的数组元素的位置先后。指针运算比较指针变量,逆序输出数组元素。12-4.c#includestdio.hvoidmain(){inta[10]={1,3,5,7,9,11,13,15,17,19};int*p1=&a[0],*p2=&a[9],t;while(p1p2){t=*p1;*p1=*p2;*p2=t;p1++;p2--;}for(t=0;t10;t++)printf(a[%d]=%d\n,t,a[t]);}28指向数组的指针一维数组的指针由于在内存中数组中的所有元素都是连续排列的,所以通过数组的首地址加上偏移量就可得到其他元素的地址。引用数组元素的表达式数组元素b[3]可以用*(bPtr+3)来引用–3是偏移量–这种表示法称为指针偏移量表示法还可以用bPtr[3]来引用–称为指针下标表示法–与b[3]相同还可以用*(b+3)来引用指针29指针与数组一维数组的指针引用数组元素的表达式12-6-1/2/3.c指针main(){inti,a[5]={1,2,3,4,5};for(i=0;i5;i++)printf(%2d,a[i]);}下标法main(){inti,a[5]={1,2,3,4,5};for(i=0;i5;i++)printf(%2d,*(a+i));}地址法main(){inta[5]={1,2,3,4,5},*p;for(p=a;p(a+5);p++)printf(%2d,*p);}指针法a[i]*(a+i)*(p+i)p[i]30指针与数组数组和指针互换使用时的注意事项数组名是一个指针常量。指针因为a是数组名,即数组的首地址,它的值在程序运行期间是固定不变的!是一个常量。错main(){inta[5]={1,2,3,4,5},*p;for(p=a;a(p+5);a++)printf(%2d,*a);}31指针与数组数组和指针互换使用时的注意事项注意指针变量的值。指针要注意指针变量的当前值。ppa[0]a[1]a[2]a[3]a[4]数组amain(){inti,a[5],*p;p=a;for(i=0;i5;i++)scanf(%d,p++);for(i=0;i5;i++,p++)printf(%d,*p);}错p=a;32指针与数组数组和指针互换使用时的注意事项注意运算符的优先级。12-9.c指针*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=1BCE其作用是先得到*p,再使p=p+1,指针指
本文标题:C语言教程同步课件12讲(第9章)
链接地址:https://www.777doc.com/doc-2907991 .html