![c++實(shí)現(xiàn)內(nèi)存拷貝的函數(shù)_第1頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb1.gif)
![c++實(shí)現(xiàn)內(nèi)存拷貝的函數(shù)_第2頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb2.gif)
![c++實(shí)現(xiàn)內(nèi)存拷貝的函數(shù)_第3頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb3.gif)
![c++實(shí)現(xiàn)內(nèi)存拷貝的函數(shù)_第4頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb4.gif)
![c++實(shí)現(xiàn)內(nèi)存拷貝的函數(shù)_第5頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb/6345b8e6-1e97-4caf-86d1-2ca7b5d9d7bb5.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、寫一個(gè)函數(shù),完成內(nèi)存移動(dòng),并為其寫一個(gè)簡(jiǎn)單的測(cè)試用例來(lái)進(jìn)行測(cè)試。夠簡(jiǎn)單的吧?有的同學(xué)很快就寫出了答案,詳見程序清單1與程序清單2。程序清單 1 V0.1版程序void MyMemMove(char *dst,char *src,int count)while(count-)*dst+ = *src+;程序清單 2 測(cè)試用例void Test()char p1256 = ”hello,world!”;char p2256 = 0;MyMemMove(p2,p1,strlen(p1);printf(“%s”,p2);客觀地講,相比那些交白卷或者函數(shù)聲明都不會(huì)寫的同學(xué)來(lái)說(shuō),能夠?qū)懗鲞@段代碼的同學(xué)已經(jīng)
2、非常不錯(cuò)了,至少在C語(yǔ)言這門課程上已經(jīng)達(dá)到了現(xiàn)行高校的教育目標(biāo),但是離企業(yè)的用人要求還有一定的距離。我們不妨將上面的程序稱為V0.1版本,看看還有沒有什么地方可以改進(jìn)。首先我們看看函數(shù)聲明是否合理,V0.1版的程序?qū)⒃吹刂泛湍康牡刂范加胏har *來(lái)表示,這樣當(dāng)然也沒有什么問(wèn)題,但是讓其他人使用起來(lái)卻很不方便,假如現(xiàn)在要將count個(gè)連續(xù)的結(jié)構(gòu)體對(duì)象移動(dòng)到另外一個(gè)地方去,如果要使用v0.1的程序的話,正確的寫法如下:MyMemMove(char *)dst,(char *)src,sizeof(TheStruct)*count)也就是說(shuō)我們需要將結(jié)構(gòu)體指針強(qiáng)制轉(zhuǎn)換成char * 才能夠正常工作
3、,這樣除了字符串以外其它的類型都不可避免地要進(jìn)行指針強(qiáng)制轉(zhuǎn)換,否則編譯器就會(huì)呱呱叫,比如在VC+2008下就會(huì)出現(xiàn)這樣的錯(cuò)誤:error C2664: 'MyMemMove' : cannot convert parameter 1 from 'TheStruct *' to 'char *'那么如何解決這個(gè)問(wèn)題呢?其實(shí)很簡(jiǎn)單,我們知道有一種特別的指針,任何類型的指針都可以對(duì)它賦值,那就是void *,所以應(yīng)該將源地址和目的地址都用void*來(lái)表示。當(dāng)然函數(shù)體的內(nèi)容也要作相應(yīng)的改變,這樣我們就得到了V0.2版的程序。程序清單 3 V0.2版程序v
4、oid MyMemMove(void *dst,void *src,int count)while (count-)*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;有的同學(xué)可能會(huì)問(wèn),這里面不是還有指針強(qiáng)制轉(zhuǎn)換嗎?只不過(guò)是換了地方。沒錯(cuò),強(qiáng)制指針轉(zhuǎn)換確實(shí)是從使用者的代碼轉(zhuǎn)移到了庫(kù)的代碼里,但我們可以將MyMemMove理解為庫(kù),而將Test理解為使用者,事實(shí)上通過(guò)調(diào)整之后的效果卻有天壤之別,V0.1是一逸永勞,而V0.2是一勞永逸!還有幾個(gè)細(xì)節(jié)需要注意,為了實(shí)現(xiàn)鏈?zhǔn)奖磉_(dá)式,我們應(yīng)該將返回值也改為voi
5、d *。此外,如果我們不小心將“*(char *)dst = *(char *)src;”寫反了,寫成“*(char *)src = *(char *)dst;”編譯照樣通過(guò),而為了找出這個(gè)錯(cuò)誤又得花費(fèi)不少時(shí)間。注意到src所指向的內(nèi)容在這個(gè)函數(shù)內(nèi)不應(yīng)該被改變,所有對(duì)src所指的內(nèi)容賦值都應(yīng)該被禁止,所以這個(gè)參數(shù)應(yīng)該用const修飾,如果有類似的錯(cuò)誤在編譯時(shí)就能夠被發(fā)現(xiàn):error C3892: 'src' : you cannot assign to a variable that is const作為程序員犯錯(cuò)誤在所難免,但是我們可以利用相對(duì)難犯錯(cuò)誤的機(jī)器,也就是編譯器來(lái)降
6、低犯錯(cuò)誤的概率,這樣我們就得到了V0.3版的程序。程序清單 4 V0.3版程序void * MyMemMove(void *dst,const void *src,int count)void *ret=dst;while (count-)*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;return ret;現(xiàn)在再來(lái)考慮這樣一種情況,有使用者這樣調(diào)用庫(kù):MyMemMove(NULL,src, count),這是完全可能的,因?yàn)橐话銇?lái)說(shuō)這些地址都是程序計(jì)算出來(lái)的,那就難免會(huì)算錯(cuò),出現(xiàn)零地址或者其它的非
7、法地址也不足為奇??梢灶A(yù)料的是,如果出現(xiàn)這種情況的話,則程序馬上就會(huì)down掉,更糟糕的是你不知道錯(cuò)誤出在哪里,于是不得不投入大量的精力在浩瀚的代碼中尋找bug。解決這類問(wèn)題的通用辦法是對(duì)輸入?yún)?shù)作合法性檢查,也就是V0.4版程序。程序清單 5 V0.4版程序void * MyMemMove(void *dst,const void *src,int count)void *ret=dst;if (NULL=dst|NULL =src)return dst;while (count-)*(char *)dst = *(char *)src;dst = (char *)dst + 1;src =
8、 (char *)src + 1;return ret;上面之所以寫成“if (NULL=dst|NULL =src)”而不是寫成“if (dst = NULL | src = NULL)”,也是為了降低犯錯(cuò)誤的概率。我們知道,在C語(yǔ)言里面“=”和“=”都是合法的運(yùn)算符,如果我們不小心寫成了“if (dst = NULL | src = NULL)”還是可以編譯通過(guò),而意思卻完全不一樣了,但是如果寫成“if (NULL=dst|NULL =src)”,則編譯的時(shí)候就通不過(guò)了,所以我們要養(yǎng)成良好的程序設(shè)計(jì)習(xí)慣:常量與變量作條件判斷時(shí)應(yīng)該把常量寫在前面。V0.4版的代碼首先對(duì)參數(shù)進(jìn)行合法性檢查,如
9、果不合法就直接返回,這樣雖然程序dwon掉的可能性降低了,但是性能卻大打折扣了,因?yàn)槊看握{(diào)用都會(huì)進(jìn)行一次判斷,特別是頻繁的調(diào)用和性能要求比較高的場(chǎng)合,它在性能上的損失就不可小覷。如果通過(guò)長(zhǎng)期的嚴(yán)格測(cè)試,能夠保證使用者不會(huì)使用零地址作為參數(shù)調(diào)用MyMemMove函數(shù),則希望有簡(jiǎn)單的方法關(guān)掉參數(shù)合法性檢查。我們知道宏就有這種開關(guān)的作用,所以V0.5版程序也就出來(lái)了。程序清單 6 V0.5版程序void * MyMemMove(void *dst,const void *src,int count)void *ret=dst;#ifdef DEBUGif (NULL=dst|NULL =src)re
10、turn dst;#endifwhile (count-)*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;return ret;如果在調(diào)試時(shí)我們加入“#define DEBUG”語(yǔ)句,增強(qiáng)程序的健壯性,那么在調(diào)試通過(guò)后我們?cè)俑臑椤?undef DEBUG”語(yǔ)句,提高程序的性能。事實(shí)上在標(biāo)準(zhǔn)庫(kù)里已經(jīng)存在類似功能的宏:assert,而且更加好用,它還可以在定義DEBUG時(shí)指出代碼在那一行檢查失敗,而在沒有定義DEBUG時(shí)完全可以把它當(dāng)作不存在。assert(_Expression)的使用非常簡(jiǎn)單,當(dāng)_E
11、xpression為0時(shí),調(diào)試器就可以出現(xiàn)一個(gè)調(diào)試錯(cuò)誤,有了這個(gè)好東西代碼就容易多了。程序清單 7 V0.6版程序void * MyMemMove(void *dst,const void *src,int count)assert(dst);assert(src);void *ret=dst;while (count-)*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;return ret; 到目前為止,在語(yǔ)言層面上,我們的程序基本上沒有什么問(wèn)題了,那么是否真的就沒有問(wèn)題了呢?這就要求程序
12、員從邏輯上考慮了,這也是優(yōu)秀程序員必須具備的素質(zhì),那就是思維的嚴(yán)謹(jǐn)性,否則程序就會(huì)有非常隱藏的bug,就這個(gè)例子來(lái)說(shuō),如果用戶用下面的代碼來(lái)調(diào)用你的程序。程序清單 8 重疊的內(nèi)存測(cè)試void Test()char p 256= "hello,world!"MyMemMove(p+1,p,strlen(p)+1);printf("%sn",p);如果你身邊有電腦,你可以試一下,你會(huì)發(fā)現(xiàn)輸出并不是我們期待的“hhello,world!”(在“hello world!”前加個(gè)h),而是“hhhhhhhhhhhhhh”,這是什么原因呢?原因出在源地址區(qū)間和目的地
13、址區(qū)間有重疊的地方,V0.6版的程序無(wú)意之中將源地址區(qū)間的內(nèi)容修改了!有些反映快的同學(xué)馬上會(huì)說(shuō)我從高地址開始拷貝。粗略地看,似乎能解決這個(gè)問(wèn)題,雖然區(qū)間是重疊了,但是在修改以前已經(jīng)拷貝了,所以不影響結(jié)果。但是仔細(xì)一想,這其實(shí)是犯了和上面一樣的思維不嚴(yán)謹(jǐn)?shù)腻e(cuò)誤,因?yàn)橛脩暨@樣調(diào)用還是會(huì)出錯(cuò):MyMemMove( p, p+1, strlen(p)+1);所以最完美的解決方案還是判斷源地址和目的地址的大小,才決定到底是從高地址開始拷貝還是低地址開始拷貝,所以V0.7順利成章地出來(lái)了。程序清單 9 V0.7版程序void * MyMemMove(void *dst,const void *src,in
14、t count)assert(dst);assert(src);void * ret = dst;if (dst <= src | (char *)dst >= (char *)src + count) while (count-) *(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;else dst = (char *)dst + count - 1;src = (char *)src + count - 1;while (count-) *(char *)dst = *(char *)src;dst = (char *)dst - 1;src = (char *)src - 1;return(ret);經(jīng)過(guò)以上7個(gè)版本的修改,我們的程序終于可以算是“工業(yè)級(jí)”了?;仡^再來(lái)看看前面的測(cè)試用例,就會(huì)發(fā)現(xiàn)那根本就算不上是測(cè)試用例,因?yàn)樗徽{(diào)用了最正常的一種情況,根本達(dá)不到測(cè)試的目的。有了上面的經(jīng)歷,測(cè)試用例也就相應(yīng)地出現(xiàn)了,我們不妨用字符數(shù)組來(lái)模擬內(nèi)存。程序清單 10 相對(duì)全面的測(cè)試用例void Test()char p1256 = "hello,world!"char p2256 = 0;MyMe
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 傳染病防治法規(guī)與實(shí)操考核試卷
- 手機(jī)信號(hào)增強(qiáng)技術(shù)考核試卷
- 天然氣的供應(yīng)安全與供應(yīng)保障考核試卷
- 建筑物清潔服務(wù)行業(yè)人才培養(yǎng)與交流考核試卷
- D掃描設(shè)備考核試卷
- 2025-2030年手術(shù)顯微鏡高清視頻錄制企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力戰(zhàn)略研究報(bào)告
- 2025-2030年插畫包裝設(shè)計(jì)行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢報(bào)告
- 2025-2030年可再生能源建筑一體化企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力戰(zhàn)略研究報(bào)告
- 2025-2030年手持式計(jì)算器創(chuàng)新企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力戰(zhàn)略研究報(bào)告
- 2025-2030年整形外科手術(shù)模擬系統(tǒng)行業(yè)跨境出海戰(zhàn)略研究報(bào)告
- 廣州市勞動(dòng)仲裁申請(qǐng)書
- 江西省上饒市高三一模理綜化學(xué)試題附參考答案
- 23-張方紅-IVF的治療流程及護(hù)理
- 頂部板式吊耳計(jì)算HGT-20574-2018
- 因數(shù)和倍數(shù)復(fù)習(xí)思維導(dǎo)圖
- LY/T 2986-2018流動(dòng)沙地沙障設(shè)置技術(shù)規(guī)程
- GB/T 16288-1996塑料包裝制品回收標(biāo)志
- 三級(jí)教育考試卷(電工)答案
- 醫(yī)院標(biāo)準(zhǔn)化運(yùn)營(yíng)管理課件
- 物業(yè)服務(wù)投標(biāo)文件
- 《數(shù)值分析》配套教學(xué)課件
評(píng)論
0/150
提交評(píng)論