《2022年地址和指针 .pdf》由会员分享,可在线阅读,更多相关《2022年地址和指针 .pdf(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第八章地址和指针81 变量的地址和指针a p 2001 一、概念1、计算机内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号(称为内存地址)2、若在程序中定义了一个变量,系统就会根据变量的类型为其分配一定字节数的内存空间,这样变量的内存地址也就确定了,即为该变量所在存储单元的第一个字节地址。3、程序中对变量的存取操作实际是对某个地址的存储单元进行操作,这里的存取方式有两种:1)直接存取:直接按变量的地址来存取变量值的方式2)间接存取:通过一个间接变量p 来存放变量a的地址,这样我们要存取a 先要找到 p 的地址,从中找出a 的地址,然后再去访问由该地址所指向的存储单元。这里,我们把
2、存放地址的变量p 称为指针变量。4、说”指针变量p 指向了变量a”的含义是指:指针变量p 中存放了变量a的地址。5、在某些场合,指针是使运算得以进行的唯一途径。1001 2001 1003 名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 15 页 -二、给指针变量赋值一个指针变量可以通过不同的方式获得一个确定的地址值,从而指向一个具体的对象。1、通过求地址运算符(&)获得地址值1)单目运算符&用来求出运算对象的地址,以此可以把一个变量的地址赋给指针变量。如:int k,*p,*q;p=&k;即把变量 k 的地址赋予了p,p k 这时可以说p 指向了 k.2)求地址运算符&只能应用
3、于变量和数组元素,不能用于表达式、常量和register 变量&运算符必须放在运算对象的左边,而且运算对象的类型必须与指针变量的基类型相同3)在调用scanf函数时,如果有q=&k;时,那么scanf(%d”,&k)和 scanf(“%d”,q)是等价的。2、通过指针变量获得地址值 1)可以通过赋值运算把一个指针变量中的地址值赋给另一个指针变量,从而使这两个指针指向同一地址,如 p=q;2)当进行赋值运算时,赋值号两边的指针变量的基类型必须相同。10名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 15 页 -3、通过标准函数获得地址值即通过调用库函数malloc 和 calloc
4、在内存中开辟动态存储单元,从而把该存储单元的地址赋给指针变量。4、给指针变量赋“空”值 1)除了给指针变量赋地址值外,还可以给指针变量赋NULL值。如:p=NULL;等价于 p=0;或 p=0;2)在使用 NULL时,应该在程序的前面加预定行:#include.NULL的值为 0,当执行了以上的赋值语句后,称p 为空指针。在这里,指针p 并不是指向地址为0 的存储单元。8.2、对指针变量的操作 1、通过指针来引用一个存储单元间接访问运算符(间址运算符)“*”是以单目运算符 1)int*p,i=10,j;p=&i;则 j=*p;j=i;j=*(&i);j=*&i;2)*p=*p+1;k=k+1;
5、+*p;(*p)+;这里括号不能少如果写成*p+,则是先将*p 作为表达式的值,然后使指针变量 p 本身加 1,指向了下一个存储单元。m=*p+;m=*p;p+;名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 15 页 -k l h j 100 200 300 400 p 3)若有以下定义:int*p,*s,k=20;s=&k;p=&s;则变量 p,s和 k 的关系可用下图表示:p s k 这里的 p 为指向指针的指针变量。2、应用举例用指针指向两个变量,通过指针运算求出值小的那个数。#include void main()int a,b,min,*pa,*pb,*pmin;sc
6、anf(“%d%d”,pa,pb);printf(“a=%d,b=%dn”,a,b);*pmin=*pa;if(*pa*pb)*pmin=*pb;printf(“min=%dn”,min);以上程序说明当指针指向变量时,完全可以通过指针来对所30 名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 15 页 -指存储单元进行存取操作。二、移动指针1、所谓移动指针是指对指针变量加上或减去一个整数,或 通过赋值运算使指针变量指向相邻的存储的单元。注意:只有当指针指向一串连续的存储单元时,指针移动才有意义。a0 a1 a2 a3 a4 11 22 33 44 55 p q 这里可以有运算:
7、q=p+2;p+;q-;q+;2、当指针指向一串连续的存储单元时,可以对指向同一串连续存储单元的两个指针进行相减的运算。比如:q-p=2;*q-*p=33-11=22;这里的“2”不是指十进制数“2”,而是指的是2 个存储单元的长度,至于是多少个字节数,与该指针变量的基类型有关。如 p 和 q 的基类型为int 型,则对应的一个存储单元长度为 4 个字节。3、当移动指针时,基类型为int 的指针只能用来指向int变量,不能用来指向其他类型的变量,否则,当移动指针时,对于整数“1”,系统将按照基类型来确定移动多少个字节。名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 15 页 -a
8、0 a1 a2 a3 a4 110 22.0 33.0 44.0 55.0 p q 三、指针比较在关系表达式中,可以对两个指针进行比较。比如:int a5=11,22,33,44,55,*p,*q;p=a0;q=a2;if(pq)printf(“pq”);8.3 指针在函数中的应用及举例一、形参为指针变量时实参和形参之间的数据传递1)若函数的形参为指针类型,调用该函数时,对应的实参必须是基类型相同的地址值或者是已赋值的指针变量。2)例如:编写函数add(int*a,int*b),函数中把指针a 和 b所指的存储单元中的两个值相加,然后将和作为函数值返回。#include int add(int
9、*a,int*b)int sum;sum=*a+*b;return sum;名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 15 页 -void main()int x,y,z;printf(“input x and y:”);scanf(“%d%d”,&x,&y);z=add(&x,&y);printf(“%d+%d=%dn”,x,y,z);二、通过传送地址值在被调用函数中直接改变调用函数中变量的值1)把数据从被调函数返回调用函数的唯一途径是通过return 语句返回函数值,因此就限定了只能返回一个值。下面我们通过举例实现将两个或两个以上的数据从被调函数返回到调用函数。2)举例
10、 1#include void swap(int*a,int*b)int t;printf(“(2)a=%d b=%dn”,*a,*b);t=*a;*a=*b;*b=t;printf(“(3)a=%d b=%dn”,*a,*b);void main()名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 15 页 -int x=30,y=20;printf(“(1)x=%d y=%dn”,x,y);swap(&x,&y);printf(“(4)x=%d y=%dn”,x,y);说明:没有通过return 语句返回值,所以swap 函数类型定义为 void 型,从上述例子中,我们可以通过
11、传送地址的方式在被调函数中直接改变调用函数中变量的值,从而来达到数据之间的传递。3)编写函数,使调用函数中的第一个实参总是存放两个数中较小的数,第二个参数存放较大的数。#include void order(int*a,int*b)int t;if(*a*b)t=*a;a=b;*b=t;void main()int x,y;printf(“input x and y:”);scanf(“%d%d”,&x,&y);printf(“x=%d,y=%dn”,x,y);order(&x,&y);名师资料总结-精品资料欢迎下载-名师精心整理-第 8 页,共 15 页 -printf(“x=%d,y=%d
12、n”,x,y);说明:在 order 函数,if(*a*b)实际上是比较main 函数中变量 x 和 y 的值。三、函数返回地址值函数值的类型除了可以是简单的数据类型外,还可以是指针类型。例如:编写函数把主函数中存放较大数的地址作为函数值返回。#include int*fun(int*a,int*b)if(*a*b)return a;else return b;void mian()int*p,m,n;printf(“input m and n:”);scanf(“%d%d”,&m,&n);printf(“m=%d,n=%dn”,m,n);p=fun(&m,&n);printf(“m=%d,n
13、=%d,*p=%dn”,m,n,*p);名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共 15 页 -输入:99 101 输出:m=99,n=101,*p=101.8.4 习题讲解:1.有以下程序(2009 年真题)#include void f(int*p,int*q);void main()int m=1,n=2,*r=&m;f(r,&n);printf(“%d,%d”,m,n);void f(int*p,int*q)p=p+1;*q=*q+1;则程序运行后的输出结果为_A_ A)1,3 B)2,3 C)1,4 D)1,2 2.(2009 年 3 月真题)有以下程序:#incl
14、ude void fun(int*a,int*b)int*c;c=a;a=b;b=c;void main()名师资料总结-精品资料欢迎下载-名师精心整理-第 10 页,共 15 页 -int x=3,y=5,*p=&x,*q=&y;fun(p,q);printf(%d,%d,*p,*q);fun(&x,&y);printf(%d,%dn,*p,*q);程序运行后的输出结果是_B_ A)3,5,5,3 B)3,5,3,5 C)5,3,3,5 D)5,3,5,3 3.有以下程序:(2009 年 3 月真题)#include void fun(char*s)while(*s)if(*s%2=0)pr
15、intf(%c,*s);s+;void main()char a=good;fun(a);printf(n);注意:字母 a 的 ASCII 码值为 97,程序运行后的输出结果是:A)d B)go C)god D)good 4.有以下程序:#include 名师资料总结-精品资料欢迎下载-名师精心整理-第 11 页,共 15 页 -int b=2;int fun(int*k)b=*k+b;return(b);void main()int a10=1,2,3,4,5,6,7,8,i;for(i=2;i4;i+)b=fun(&ai)+b;printf(“n”);程序运行后的输出结果是_C_ A)1
16、0 12 B)8 10 C)10 28 D)10 16 5.(P102 8.3)若有以下程序:#include void sub(int x,int y,int*z)*z=y-x;void main()int a,b,c;sub(10,5,&a);sub(7,a,&b);sub(a,b,&c);printf(“%d,%d,%dn”,a,b,c);6.(P102 8.4)若有以下程序:#include“stdio.h”void main()int k=2,m=4,n=6,*pk=&k,*pm=&m,*p;名师资料总结-精品资料欢迎下载-名师精心整理-第 12 页,共 15 页 -*(p=&n)=
17、*pk*(*pm);printf(“%dn”,n)则程序的输出结果是A)4 B)6 C)8 D)10 7.(P102 8.5)若指针p 已正确定义并指向如图所示的存储单元:a0 a1 a2 a3 a4 10 20 30 40 50 则执行语句*p+后,*p 的值是:A)20 B)30 C)21 D)31 8.(P102 8.6)若指针 p 已正确定义并指向如图所示的存储单元,则表达式*+p 的值是:A)20 B)30 C)21 D)31 9.(P102 8.7)若指针p 已正确定义并指向如图所示的存储单元,则表达式+*p 的值是:A)20 B)30 C)21 D)31 10.(P103 8.1
18、1)若有以下程序:#include“stdio.h”void sub(double x,double*y,double*z)*y=*y-1.0;*z=*z+x;void main()double a=2.5,b=9.0,*pa,*pb;pa=&a;pb=&b;sub(b-a,pa,pa);printf(“%fn”,a);名师资料总结-精品资料欢迎下载-名师精心整理-第 13 页,共 15 页 -11.编程,请编写函数,对传送过来的三个数选出最大数和最小数,并通过形参传回调用函数。(用指针实现)#include“stdio.h void swap(int*p1,int*p2,int*p3)int
19、 t;if(*p1*p2)t=*p1,*p1=*p2,*p2=t;if(*p1*p3)t=*p1,*p1=*p3,*p3=t;if(*p2*p3)t=*p2,*p2=*p3,*p3=t;void main()int a,b,c;scanf(“%d%d%d”,&a,&b,&c);swap(&a,&b,&c);printf(“min=%d,max=%dn”,a,c);12.编写函数对传送过来的两个浮点数求和与差,并通过函数调用传回调用函数。#include stdio.h void fun(double x,double y,double*s1,double*s2)*s1=x+y;*s2=x-y;void main()double a,b;名师资料总结-精品资料欢迎下载-名师精心整理-第 14 页,共 15 页 -scanf(%lf,%lf,&a,&b);fun(a,b,&a,&b);printf(%f,%fn,a,b);名师资料总结-精品资料欢迎下载-名师精心整理-第 15 页,共 15 页 -