![]() ![]() |
|
针对C语言功力测试题的讲解分析 | |
作者:佚名 文章来源:不详 点击数 更新时间:2008/4/18 14:00:30 文章录入:杜斌 责任编辑:杜斌 | |
|
|
char str[10]; //问:strlen(str)和sizeof(str)的值分别是多少? // strlen(str) 值不确定,strlen根据’\0’确定字符串是否结束。 // sizeof(str)=10 sizeof一个数组为数组长度 strcpy(str,"www.it315.org"/*共13个字母*/); //问:此时x和strlen(str)的值分别是多少? // x 为35 // strcpy(char* dest, const char* src) // 根据src来复制dest,依照src的’\0’决定复制的长度,而dest必须要提供足够的长度,这里会引起溢出,strlen返回13,但是数组外部的数据已经被破坏 str="it315.org";//编译能通过吗? // 数组不能赋值,只能初始化。char str[10] = "it315.org"; // 而且初始化时编译器会检查数组的长度与初始化串的长度是否匹配 char *pstr; strcpy(pstr,"http://www.it315.org); //上句编译能通过吗?运行时有问题吗? // 可以通过编译,但是pstr指向了常量区,运行时最好只做读操作,写操作不保险 ![]()
pstr=3000;//编译能过吗?如果不行,该如何修改以保证编译通过呢? // 不能通过,char* pstr表示pstr是个字符指针,不能指向3000的整形变量。 // 修改的话,可以这样:pstr = (char*)3000,把pstr指向3000这个地址; long y=(long)pstr;//可以这样做吗? // 可以,y的值为pstr所指的地址。不过如果是纯粹要地址的话,最好是用unsigned long。 int *p=str; *p=0x00313200; printf("%s",str);//会是什么效果?提示0x31对应字符’1’,0x32对应字符’2’。 // 首先编译未必会过关,有些编译器可能不允许int * 直接指向char*。最好是改为int *p = (int*)str; // 过关了效果就是什么东西都没有。int *p=str; p为str所指的地址,*p表示修改了str所指向的内存。 // 由于sizeof(int)在32位机上,int有4个字节(其实具体要看编译器的配置文件,好像是limit.h,一般是4个字节)所以修改了str[0]-str[3] // 由于0x00313200头尾都是0,所以字符串为’\0’开头,什么都打印不出来。这里有个big-endin和little-endin的问题。以0x31323334为例 // little-endin的机器上面,0x31323334在内存中排列顺序为34 33 32 31,输出为4321,如intel芯片的pc // big-endin机器上面为31 32 33 34 ,输出为1234,如ibm powerpc p=3000;//p+1的结果会是多少? // 3000+sizeof(int); 指针+1均为原来地址加上sizeof(指针所指的数据类型) char *pc=new char[100];//上述语句在内存中占据几个内存块,怎样的布局情况? // 本身pc会占用函数栈一个4字节的指针长度(具体是否为4个字节要看机器和编译器)。 // new会在堆上申请100个字节sizeof(char)的连续空间。 void test(char **p) { *p=new char[100]; }//这个编译函数有问题吗?外面要调用这个函数,该怎样传递参数? // 该程序没有问题。需要在函数中对指针所指的地址进行变化是必须传人指针的地址。 // 原因是这样的:如果传入的为指针本身,在函数调用的时候,实参会被复制一个实例,这样就不是原来的指针了,对该指针本身进行的任何改变都不能传递回去了。 // 可以这样理解,如果传入的参数为int,那么对int本身的值的改变就传不回去啦,加个*也是一样的。 //能明白typedef int (*pfun)(int x,int y)及其作用吗? // 定义了一个函数指针类型的宏,这样pfun就表示指向返回值为int,且同时带2个int参数的函数指针类型了。 // 可以用来定义这样的变量: // 比如有个函数为int fun( int x, int y ); // pfun p = fun;
补充: 第二题: 其他编译器下没试,但在vc++环境下,x的值是要改变的.虽然表面上看来,在程序中并没有修改x的值,但是实际运行的结果是上面的x的值发生了修改,这是因为strcpy以后,把多余的数据拷贝进了str的邻居(int类型的x)中,所以x的数据也就变了.这是一个曾让我刻骨铭心的问题,在我刚出道时遇到这个问题,虽然在朋友的帮助下解决了这个问题,但一直不明白x的值为何变了,只有最后走上培训教师的岗位,才开始梳理自己曾经的困惑,才开始总结以前的经验供学员们借鉴.我觉得这个题目的价值非常之大,它能引起学员对字符串拷贝越界问题的足够重视,并且通过这个问题更能明白字符串的处理是怎么回时,更能明白字符串与字符数组的关系:字符串就是一个字符数组,只是把这个字符数组用在处理串的函数中时,这些函数不考虑数组的长度,只是记住数组的首地址,从首地址开始处理,并在遇到0时 结束处理, 最后一题: 函数指针最大的用处在于它可以被一个模板方法调用,这是我在学java的设计模式时领悟到的.例如,有两个函数的流程结构完全一致,只是内部调用的具体函数不同,如下所示: void func1() { //一段流程代码和面向方面的代理,如安全检查,日志记录等 int sum = add( x , y); //一段流程代码和面向方面的代理,如安全检查,日志记录等 } void func2() { //与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等 int difference = sub( x , y); //与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等 } 那么,可以只定义一个函数,如下所示 void func(pfunc p) { //与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等 int difference = p( x , y); //与func1完全相同的一段流程代码和面向方面的代理,如安全检查,日志记录等 } 调用程序在调用时,让参数p分别指向add和sub函数就可以了. |
|
![]() ![]() |