Posted on 2010-04-23 23:45
besterChen 閱讀(2732)
評論(24) 編輯 收藏 引用 所屬分類:
C/C++/STL/boost 、
心情日志
題目要求:
純C 、不準使用匯編,不準使用臨時變量(當然包括全局變量)實現(xiàn)一個strlen 函數(shù)。
就是說,可以利用的資源只有那個參數(shù),但是有個要求就是不許破壞原字符串。
我能想到的方法就是遞歸,所以我給出的答案是:
unsigned int mystrlen(char *pszString)
{
if (*pszString == '\0')
{
return 0;
}
return mystrlen(++pszString)+1;
}
出題的朋友說,這樣跟算是使用了內(nèi)存,而且這樣遞歸會溢出,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了,經(jīng)過一個小時的漫長等待,出題的朋友給出了經(jīng)典的讓人吐血的答案:
strlen(char *p)
{
if(p[0] == 0) return 0;
if (p[1] == 0) return 1;
.....
if(p[10000] == 0) return 10000;
....
}
哎……
下面是應 OnTheWay 朋友的要求,給出的解釋:
首先,題目本身的性質(zhì),我感覺就是消遣,肯定不會有人無聊到不用變量寫strlen,也肯定不會應用到實際情況,所以,大家不要太認真……
再就是從技術的角度來講,空明流轉(zhuǎn) 和 OnTheWay 說的 訪問非法內(nèi)存 我覺得應該不是這樣的,下面就我的理解,做出的解釋如下:
/**************************************************************************
介于各位看官C水平不同,我在函數(shù)中做點兒解釋性的說明。
當然,由于本人水平也很菜,注釋僅限個人理解范疇,如有不對,請批評指正……
****************************************************************************/
int StrLlen(char * p)
{
// (int *)&p 這個應該不用解釋,就是取參數(shù)的地址。
// sizeof(int) * 2 求出兩個int的大小。
*((int *)&p - sizeof(int) * 2 ) = 0;
// 由于這里是減一個數(shù)值,由此,這句話就相當于申請兩個int變量,并將第一個變量初始化為0。
// 如果這句話變成*((int *)&p + sizeof(int) * 2 ) = 0; 那就破壞了程序的參數(shù),算是非法訪問內(nèi)存,可是人家是減的不是加
while ( (*p))
{
(*((int *)&p - sizeof(int) * 2 ))++; // 使用剛才申請的變量作為累加器,存放字符串長度。
p++;
}
return *((int *)&p - sizeof(int) * 2 ); // 返回字符串長度。
}
以上注釋,純粹是我的個人理解,本人剛學C語言,理解可能有誤,所以特地寫了一個測試程序,驗證一下上面的注釋:

查看程序運行情況,看看是否有問題……

運行沒有問題,再調(diào)試看看內(nèi)存情況:

我截取的匯編代碼,相關的內(nèi)存情況我也截取了,有匯編有真相……

這里跟我預期想的減兩個int大小有點出入,為什么減的是0x20?有待繼續(xù)考證,不過不影響我們的理解,它是減的地址,相當于申請變量,減0x20相當于申請了8個變量,而不是加了0x20,因此棧內(nèi)存是安全的,不存在非法操作內(nèi)存的情況……
另外,這個就是一個娛樂,如果我的解釋看官明白了,我很欣慰,如果我講述的有問題,請回復我,我修改,如果沒看明白,就當我在逗自己玩……