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

查看程序運(yùn)行情況,看看是否有問題……

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

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

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