您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > C语言内涵教程练习9参考答案
9.1存储单元的地址仅表明其首字节在内存中的位置,只有地址无法确定相关储存单元的大小及编码格式。只有知道了类型,才能确定相关存储单元的大小及编码格式,才能使用存储单元,因此,有类型的地址可以确定存储单元。9.2整型变量存储整数,指针变量存储地址。指针与内存地址的关系似乎更像整型与整数的关系。准确地说,指针变量存储的是存储单元的地址而并非简单的内存地址。简单的内存地址可以看成一个整数,但存储单元的地址应理解成具有类型的地址。9.3地址是整数,但整数不是地址。多次强调,存储单元的地址有类型,而指针变量也只能用规定类型的存储单元的地址赋值。更进一步,指针变量只能指向程序拥有的存储单元。因此,通常不能用整数给指针变量赋值。理论上不可以,只有同类型间的指针变量才可以相互赋值,但实际上C语言追求效率,不保证类型安全,有些C语言编译系统“允许”不同类型的指针变量之间相互赋值。即使单精度指针变量pf真的指向了整型变量i,通过*pf使用变量i的存储单元也没有太大的实际意义。9.4不等价。double*p=&lf;是初始化语句,定义了一个双精度指针变量p,并且它被赋值为变量lf的地址;语句*p=&lf;是赋值语句,把变量lf的地址赋值给指针变量p指向的存储单元,这条语句有两个问题,首先指针变量p没有指向合法的存储单元,不能以间接引用*p的方式使用非法的存储单元,其次,*p标识存储单元的类型为双精度,不能接受变量lf的地址,两者类型不匹配。double*p=&lf;的作用等同于double*p;p=&lf;。9.5程序的运行结果为:因为语句printf(“%x”,-5);的输出结果为fffffffb,所以变量i实际的内存状态和简化后的内存状态如下:地址变量0x0012ff7c0x0012ff7d0x0012ff7e0x0012ff7f0x0012ff80i...11111011111111111111111111111111...内容...-5...内容地址0x0012ff7c0x0012ff80实际的内存状态简化后的内存状态变量pi与变量i的关系如下:变量pi地址0x0012ff780x0012ff7c-5原始状态0x0012ff7ci-5ipi形象地表示......内容9.6指针变量用于存储某类型存储单元的地址,而存储单元的地址在VC6.0中均为32位,因此,无论何种类型的指针变量,其长度均为4个字节。sizeof(pf)的值为指针变量pf本身的长度,长度为4个字节。sizeof(*pf)的值为指针变量pf指向的存储单元的长度,即双精度型存储单元的长度,为8个字节。9.7不能用整型变量给整型指针变量赋值。可修改为:pi=&i;或pi=(int*)i;。9.8程序中指针变量p1指向了整型变量i,而语句p2=p1;使得指针变量p2也指向了整型变量i。因为*p1和*p2也标识了变量i相关的存储单元,所以语句i=*p1+*p2;相当于i=i+i;,语句执行后,变量i的值变为6。最终程序的输出结果为:6,6,6。9.9C语言中使用存储单元有直接引用和间接引用两种方法。对于指针变量p,语句p=&i;为指针变量p赋值为变量i的地址,实际上是使用直接引用的方式使用了指针变量p本身的存储单元。语句*p=23;就是所谓的以间接引用的方式使用指针变量p指向的存储单元。理论上,只要指针变量指向了某存储单元,就可以通过间接引用的方式使用该存储单元,但实际上为避免出现错误,应保证通过间接引用方式只使用合法的存储单元。表达式p标识一个可以存储某类存储单元地址的存储单元,表达式*p标识p指向的存储单元。9.10pi不是空指针!程序的输出结果为:可见在VC6.0中,没有赋值的局部指针变量会被赋值为0xcccccccc。9.11(1)无问题。(2)无问题。(3)有问题,其中p2=*p1;错误,不能用整型变量给指针变量赋值。。(4)有问题,指针变量p1指向了非法的存储单元,语句*p1=*p2;中使用了非法的存储单元。(5)无问题。(6)有问题。指针变量p1只能用整型地址赋值,语句p1=&p2;中&p2的结果并非整型地址而是整型指针地址。9.12程序的运行结果为:a=1,b=7m=6,n=9分析如下:语句a=p1==&m;中p1==&m先求值,因为指针变量p1指向了整型变量m,故求值结果为真,值为1,原语句变为a=1;。在语句b=(++*p1)/(*p2)+5;中,*p1标识了变量m相关的存储单元,即其可与m互换,*p2可与n互换,原语句可变为b=(++m)/n+5;,变量b被赋值为7,且变量m自增1后变为6。语句n=*p1+*p2;可变为n=m+n;即n=6+3;。9.13(1)#includestdio.hvoidmain(){inta,b,c,*pa=&a,*pb=&b,*pc=&c,t;printf(请输入三个整数!\n);scanf(%d%d%d,pa,pb,pc);if(*pa*pb){t=*pa;*pa=*pb;*pb=t;}if(*pb*pc){t=*pb;*pb=*pc;*pc=t;if(*pa*pb){t=*pa;*pa=*pb;*pb=t;}}printf(a=%d,b=%d,c=%d\n,a,b,c);}(2)#includestdio.hvoidmain(){inta,b,c,*pa=&a,*pb=&b,*pc=&c,*t;printf(请输入三个整数!\n);scanf(%d%d%d,pa,pb,pc);if(*pa*pb){t=pa;pa=pb;pb=t;}if(*pb*pc){t=pb;pb=pc;pc=t;if(*pa*pb){t=pa;pa=pb;pb=t;}}printf(a=%d,b=%d,c=%d\n,a,b,c);printf(%d%d%d\n,*pa,*pb,*pc);}9.14函数调用swap(*p1,*p2)的实参为两个整数,当实参给形参赋值时,会因类型不匹配而出错。函数调用swap(p1,p2)对实参求值时得到了两个整型存储单元的地址,实参给形参赋值后,两个形参分别指向了整型变量i和j,函数调用swap(p1,p2)等同于swap(&i,&j)。9.15函数调用swap(&i,&j)执行时,形参px指向整型变量i,即它的值为0x0012ff00,形参py指向了整型变量j,即它的值为0x0012ff04。函数体执行时交换了两个整型指针形参px和py的值,函数执行结束时,形参px指向了变量j,形参py指向了变量i。由于函数中并没有以间接引用的方式使用变量i和j,所以在main函数中它们并没有改变。9.16由于传值调用C语言函数中不可能改变实参的值。指针作为形参时,实参应为某个存储单元的地址,函数中获得了地址的指针型形参可以借助间接引用的方式使用它指向的存储单元,从而改变相关存储单元的内容。当认为与形参指针对应的是一个存储单元表现为地址时,可以勉强说函数中可以改变“实参”的值。确切地说指针作形参时,实参是地址,函数中可以使用(改变)此地址处的存储单元,改变并非实参本身。9.17在变量的作用域之外使用与变量相关的存储单元时需要借助间接引用的方式,此外,某些存储单元可能没有用变量标识,这类存储单元只能用间接引用的方式使用。9.18指针变量存储的是某类地址,值比较特别而已,与存储了整数的变量没有本质的区别。任何变量都有作用域和生命期的限制。9.19scanf函数的形参显然为指针类型,函数中可以改变与实参相关的存储单元。把用户输入的整数存入变量i中只需变量i的地址即可,而指针变量pi存储了变量i的地址,因此,可以用语句scanf(%d,pi);。9.20分析:p=&j;使得全局变量p指向了变量j。当test函数执行时,形参x的值为5,pi指向了变量j。*p=*pi+c;中*pi标识了变量j相关的存储单元,即把2+3的值存入变量p指向的存储单元中,语句执行结果将使与变量j相关的存储单元变成5。语句x=*pi*c中,把5*3的值存入变量x中,x的值变为15。printf调用的输出结果为15,5,5。main函数中printf调用的输出结果为5,5,5。9.21(1)voidlarger(intx,inty,int*z){if(z==NULL)return;if(xy)*z=x;else*z=y;}(2)#includestdio.h#include7_1.cvoidmain(){floatm=3.2,n=2.3;inti;larger(m+n,m-n,&i);printf(%.1f和%.1f中较大者为%d\n,m+n,m-n,i);}思考:可以定义一个单精度变量f(floatf;)再用larger(m+n,m-n,&f);求出较大者吗?9.22voidfac(intn,unsignedint*re){if(n==0||n==1)*re=1;else{fac(n-1,re);*re=n**re;}}9.23(1)语句constdouble*pf=&m;中关键字const修饰的是double*可理解为指针变量pf指向的存储单元,也就是说指针变量pf可以通过赋值操作指向不同的存储单元,但它指向的存储单元不能被修改,即不能用类似*pf=3;的语句改变与变量m相关的存储单元。(2)语句doubleconst*pf=&m;中关键字const修饰的是*,同上也可理解为指针变量pf指向的存储单元。(3)语句double*constpf=&m;中关键字const修饰的是指针变量pf,即不能通过赋值操作改变它指向的存储单元了,它只能指向变量m,但可以的用类似*pf=3;的语句改变与变量m相关的存储单元。(4)语句constdouble*constpf=&m;中,指针变量pf只能指向变量m,也不能用类似*pf=3;的语句改变与变量m相关的存储单元。函数的首部类似voidtest(cosntint*pi)。9.24B和D均可以。9.25表达式*p++中优先级相同、右结合,自增操作符先求值,子表达式p++的结果为p,故原表达式实为*p,即a[1],值为2,但具有左值性。该表达式求值过程中使指针变量p自增1,再使用指针变量p时,它已经指向了数组元素a[2]。表达式*--p中,子表达式--p先求值,指针变量p先减1,即指向了数组元素a[0],故原表达式为a[0],值为1,但具有左值性。9.26一维数组由地址连续的一组变量构成,只要获得了首元素的地址,就可以很容易地访问其余的数组元素,因此,一维数组的关键在于首元素地址。一维整型数组变量a的值为其首元素的值为其首元素地址,即它指向了数组的首元素;整型指针变量pi可以指向任意的整型存储单元,当然也可以指向数组的首元素。相同点:它们都存储了整型存储单元的地址。不同点:数组变量a只能存储固定的地址,不能通过赋值操作改变它指向的存储单元;所有的数组元素的存储单元都算作数组变量a的,故它的长度较大,但整型指针变量pi的长度只有4个字节,因为VC6.0中,地址有32位。9.276.5:#includestdio.h#defineN10voidmain(){int*pi,*pmax,temp;intarr[N];printf(请输入%d个整数:\n,N);for(pi=arr;piarr+N;++pi)scanf(%d,pi);printf(处理前数组为:\n);for(pmax=pi=arr;piarr+N;++pi){printf(%d,*pi);if(*pi*pmax)pmax=pi;}for(temp=*pmax;pmaxarr+N-1;++pmax)*pmax=*(pmax+1);*pmax=temp;printf(\n处理后数组为:\n);for(pi=arr;piarr+N;++pi)printf(%d,*pi);printf(\n);}6.6:#includestdio.h#defineN10voidmain(){int*pi,*p,temp;inta[N]={20
本文标题:C语言内涵教程练习9参考答案
链接地址:https://www.777doc.com/doc-2907875 .html