您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > C语言程序设计――指针(完整版)
第九章§9.1地址和指针的概念为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。计算机中,所有的数据都是存放在存储器的内存单元中的。一般把存储器中一个字节称为一个内存单元,不同数据类型所占用的内存单元数不等,如整型变量占2个字节,字符变量占1个字节等。为了正确地访问这些内存单元,必须为每个内存单元编上号,根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号,称为“地址”。内存单元的地址和内存单元的内容是两个不同的概念:假设程序中定义了整型变量i,并赋值为3。编译时系统分配2000和2001两个字节给变量i,此时两个内存单元的编号为单元的地址,其中存放的数据即是该单元的内容。两种访问方式:直接访问方式:在程序中一般是通过变量名来对内存单元进行存取操作的,其实程序在编译后,已经将变量名转换成变量的地址,对变量值的存取都是通过地址进行的。间接访问方式:将变量i的地址存放在另一个变量中,C语言规定,可以在程序中定义一种特殊的变量,用来存放地址。假设定义一个变量p,用来存放整型变量的地址,它被分配为3010、3011两个字节。可以通过下面语句将i的地址(2000)存放到p:p=&i;对变量i是访问,可直接访问,已知变量i的地址,根据此地址直接对变量i的存储单元进行存取访问;也可间接访问,先找到存放变量i的地址的变量p,从其中得到变量i的地址,然后找到变量i的存储单元,对它进行存取范围。一个变量的地址称为该变量的“指针”。如,地址2000是变量i的指针。C语言中,用一个变量存放指针(地址),此变量称为指针变量,上述的变量p是指针变量,指针变量的值是某个内存单元的地址(指针)。严格地说,一个指针是一个地址,是一个常量;而一个指针变量却可以被赋予不同的指针值,是变量。但通常把指针变量简称指针。指针变量的值不仅可以是变量的地址,也可以是其他数据结构的地址。例如:在一个指针变量中可存放一个数组或一个函数的首地址。§9.2变量的指针和指向变量的指针变量区别:变量的指针和指针变量1.变量的指针就是变量的地址。2.存放变量地址的变量是指针变量,它用来指向另一个变量。为了表示指针变量和它所指向的变量之间的联系,在程序中用“*”符号表示“指向”。若已定义i_pointer为指针变量,则*i_pointer是i_pointer所指向的变量,因此*i_pointer也代表一个变量,它和变量i是同一回事。下面两个语句作用相同:(1)i=3;(2)*i_pointer=3;第二个语句含义是将3赋给指针变量i_pointer所指向的变量i.一、指针变量的定义指针变量在使用前必须先定义,一般形式为:类型说明符*指针变量名;其中,*表示这是一个指针变量,类型说明符表示该指针变量所指变量的数据类型。例如:int*p1;(其中p1(而不是*p1)是一个指向整型变量的指针变量,它的值是某个整型变量的地址。)float*p2;(其中p2是指向浮点型变量的指针变量)说明:(1)指针变量名的构成原则是标识符,前面必须有“*”,表示该变量的类型是指针型变量。(2)在一个定义语句中,可以同时定义普通变量、数组、指针变量。(3)类型说明符说明的数据类型不是指针变量中存放的数据的数据类型,而是它将要指向的变量或数组的数据类型。因此,一个指针变量只能用来指向同种数据类型的其他变量或数组,不能时而指向一个浮点型变量,时而指向一个整型变量。二、指针变量的引用指针变量中只能存放变量的地址,绝不能存放任何其他数据。例如:int*p;p=2000;/*2000是一个整数而不是一个地址*/C语言提供两种有关的运算符:(1)&:取地址运算符(用来表示变量的地址)(2)*:取内容运算符(用来取其指向的内容,或称“间接访问”运算符,或称指针运算符)两种运算符都是单目运算符,其结合性都为自右向左,优先级别相同。例如:&a为变量a的地址,*p为指针变量p所指向的内存单元的内容(即p所指向的变量的值)。说明:(1)设有指向整型变量的指针变量p,若要把整型变量a的地址赋予p,有以下方式:指针变量初始化的方法:inta;int*p=&a;赋值语句的方法:inta,*p;p=&a;(2)指针运算符*和指针变量说明中的指针说明符*不是一回事。后者表示其后的变量是指针类型,前者则是一个运算符用以表示指针变量所指的变量。说明:(3)如果已执行了语句p=&a;,则:&*p:先进行*p的运算,即是变量a,再执行&运算,即变量a的地址。因此&*p与&a相同。*&a:先进行&a的运算,即得a的地址,再执行*运算,即&a所指向的变量,即变量a。因此*&a与a相同。#includestdio.hvoidmain(){inta,b;int*p1,*p2;a=100;b=10;p1=&a;p2=&b;printf(“%d,%d\n”,a,b);printf(“%d,%d\n”,*p1,*p2);}例:通过指针变量访问整型变量。运行结果:100,10100,10#includestdio.hvoidmain(){inta=5,b,c,*p;p=&a;b=*p;c=a+*p;printf(“%d,%d\n”,b,c);}例:通过指针变量进行运算。运行结果:5,10说明:(1)指针变量的运算种类也是有限的,它只能进行赋值运算和部分算术运算及关系运算。(2)指针变量还可以赋空值,其赋空值后,则可以使用,只是它不指向具体的变量而已。例如:#defineNULL0int*p=NULL;三、指针变量作函数参数#includestdio.hswap(intx,inty){intt;t=x;x=y;y=t;}voidmain(){inta=3,b=5;if(ab)swap(a,b);printf(“a=%d,b=%d\n”,a,b);}C语言是通过传值将参数传递给函数的,对被调函数来说,没有直接的方法来改变主调函数内的变量的值。例:对两个整数按大小顺序输出。运行结果:a=3,b=5#includestdio.hswap(int*x,int*y){intt;t=*x;*x=*y;*y=t;}voidmain(){inta=3,b=5;if(ab)swap(&a,&b);printf(“a=%d,b=%d\n”,a,b);}使主调函数传递指向要被改变量的指针,即可使被调函数能改变主调函数的参数值。例:对两个整数按大小顺序输出。运行结果:a=5,b=3(苏小红版第11章的§11.1和§11.2)一个数组是由连续的一块内存单元组成的,数组名即是这块连续内存单元的首地址。一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。指向数组的指针变量称为数组指针变量。其一般形式为:类型说明符*指针变量名;其中,类型说明符表示所指数组的类型。从中可以看出指向数组的指针变量和指向普通变量的指针变量的说明是相同的。一、指向数组元素的指针说明:设有实型数组a,指向a的指针变量为pa,则有以下关系:pa,a,&a[0]均指向同一内存单元,它们是数组a的首地址,即是a[0]的首地址;pa+1,a+1,&a[1]均指向元素a[1]的地址;……pa+i,a+i,&a[i]均指向元素a[i]的地址。*(pa+i),*(a+i)是pa+i或a+i所指向的数组元素,即a[i]注意:pa是变量,a与&a[i]都是常量(地址)。引入指针变量后,可以用两种方法来访问数组元素:1.下标法:采用a[i]形式访问数组元素:2.指针法:采用*(pa+i)或*(a+i)形式,用间接访问的方法来访问数组元素,即通过指向数组元素的指针找到所需的元素。例:(1)inta;(2)inta;初始化赋值int*p=&a[0];int*p=a;(3)inta;(4)inta;赋值语句赋值int*p;int*p;p=&a[0];p=a;按C语言的规定:如果指针p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,而不是将p的值(地址值)简单地加1。例如:数组元素是float型,每个元素占4个字节,则p+1意味着使p的值(地址值)加4个字节,以使它指向下一个元素,此时,p+1所代表的地址实际上是p+1d,d是一个数组元素所占的字节数。二、通过指针引用数组元素(1)下标法#includestdio.hvoidmain(){inta[10],i;for(i=0;i10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i10;i++)printf(“%d”,a[i]);printf(“\n”);}例:输出数组中的全部元素。(设一个a数组,整型,有10个元素,要输出各元素的值有3种方法)(2)通过数组名计算数组元素的地址,找出元素的值for(i=0;i10;i++)printf(“%d”,*(a+i));(3)用指针变量指向数组元素for(p=a;p(a+10);p++)printf(“%d”,*p);#includestdio.hvoidmain(){inta[10],i,*p;p=a;for(i=0;i10;i++)scanf(“%d”,p++);printf(“\n”);for(i=0;i10;i++,p++)printf(“%d”,*p);printf(“\n”);}例:(改错题)通过指针变量输出a数组中的10个元素。运行结果:1234567890↙221532340030036252021163185298237284831.算术运算只能进行加减运算,数组指针变量加或减一个整数n的意义是把指针指向的当前位置(指某数组元素)向前或向后移动n个位置。例如:inta[5],*pa;pa=a;/*pa指向a[0],pa的值为&a[0]*/pa=pa+2;/*pa指向a[2],pa的值为&a[2]*/数组指针变量的运算:2.两个指针变量之间的运算只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。(1)两指针变量相减两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。两指针变量不能进行加法运算。(2)两指针变量进行关系运算指向同一数组的两个指针变量进行关系运算是表示它们所指数组元素之间的关系。例如:pa==qa表示pa和qa指向同一数组元素;qapa表示qa处于高地址位置;pa处于低地址位置;#includestdio.hvoidmain(){inta[5],i,*pa,*qa;pa=qa=a;for(i=0;i5;i++){*qa=i;qa++;}/*将指针qa指向a数组中的下一元素*/for(i=0;paqa;i++){printf(“a[%d]=%-2d”,i,*pa);pa++;}}例:通过指针变量的运算输出a数组中的5个元素。运行结果:a[0]=0a[1]=1a[2]=2a[3]=3a[4]=42.指针变量的自增自减运算如果先使p指向数组a的首元素(即p=a),请分析:(1)p++:使p指向数组a的下一元素,即a[1]。(2)*p++:由于元素符++和*同优先级,结合方向为自右向左,因此它等价于*(p++)。(3)*(p++)与*(++p)作用不同。(4)(*p)++:表示p所指向的元素值加1,它等价于(a[0])++。若a[0]=3,则(*p)++的值为4。注意:是元素值加1,而不是指针值加1。前面已介绍过可以用数组名作函数的参数,例如:voidf(intarr[],intn)voidmain(){……{intarray[10];……}f(array,10);……}f(intarr[],intn)但在编译时是将arr按指针变量处理的,相当于将函数f的首部写成f(int*arr,intn)以上两种写法是等价的。三、用数组名和数组指针变量作函数参数以变量名和数组名、数组指针变量作为函数参数的比较:
本文标题:C语言程序设计――指针(完整版)
链接地址:https://www.777doc.com/doc-3156730 .html