Posted on 2010-04-23 23:45
besterChen 阅读(2707)
评论(24) 编辑 收藏 引用 所属分类:
C/C++/STL/boost 、
心情日志
题目要求:
纯C 、不准使用汇编,不准使用临时变量(当然包括全局变量)实现一个strlen 函数。
就是说,可以利用的资源只有那个参数,但是有个要求就是不许破坏原字符串。
我能想到的方法就是递归,所以我给出的答案是:
unsigned int mystrlen(char *pszString)
{
if (*pszString == '\0')
{
return 0;
}
return mystrlen(++pszString)+1;
}
出题的朋友说,这样跟算是使用了内存,而且这样递归会溢出,PASS掉了……,没有办法,知道求助我的同学,他们给出了这样的答案:
int StrLlen(char * p)
{
*((int *)&p - sizeof(int) * 2 ) = 0;
while ( (*p))
{
(*((int *)&p - sizeof(int) * 2 ))++ ;
p++;
}
return *((int *)&p - sizeof(int) * 2 );
}
很佩服同学们的敏捷思路,不过这样算是使用临时变量呀,所以也很自然的被PASS了,经过一个小时的漫长等待,出题的朋友给出了经典的让人吐血的答案:
strlen(char *p)
{
if(p[0] == 0) return 0;
if (p[1] == 0) return 1;
.....
if(p[10000] == 0) return 10000;
....
}
哎……
下面是应 OnTheWay 朋友的要求,给出的解释:
首先,题目本身的性质,我感觉就是消遣,肯定不会有人无聊到不用变量写strlen,也肯定不会应用到实际情况,所以,大家不要太认真……
再就是从技术的角度来讲,空明流转 和 OnTheWay 说的 访问非法内存 我觉得应该不是这样的,下面就我的理解,做出的解释如下:
/**************************************************************************
介于各位看官C水平不同,我在函数中做点儿解释性的说明。
当然,由于本人水平也很菜,注释仅限个人理解范畴,如有不对,请批评指正……
****************************************************************************/
int StrLlen(char * p)
{
// (int *)&p 这个应该不用解释,就是取参数的地址。
// sizeof(int) * 2 求出两个int的大小。
*((int *)&p - sizeof(int) * 2 ) = 0;
// 由于这里是减一个数值,由此,这句话就相当于申请两个int变量,并将第一个变量初始化为0。
// 如果这句话变成*((int *)&p + sizeof(int) * 2 ) = 0; 那就破坏了程序的参数,算是非法访问内存,可是人家是减的不是加
while ( (*p))
{
(*((int *)&p - sizeof(int) * 2 ))++; // 使用刚才申请的变量作为累加器,存放字符串长度。
p++;
}
return *((int *)&p - sizeof(int) * 2 ); // 返回字符串长度。
}
以上注释,纯粹是我的个人理解,本人刚学C语言,理解可能有误,所以特地写了一个测试程序,验证一下上面的注释:
查看程序运行情况,看看是否有问题……
运行没有问题,再调试看看内存情况:
我截取的汇编代码,相关的内存情况我也截取了,有汇编有真相……
这里跟我预期想的减两个int大小有点出入,为什么减的是0x20?有待继续考证,不过不影响我们的理解,它是减的地址,相当于申请变量,减0x20相当于申请了8个变量,而不是加了0x20,因此栈内存是安全的,不存在非法操作内存的情况……
另外,这个就是一个娱乐,如果我的解释看官明白了,我很欣慰,如果我讲述的有问题,请回复我,我修改,如果没看明白,就当我在逗自己玩……