變態(tài)的命名
我們?cè)趯?xiě)程序時(shí),一般講究見(jiàn)到變量的命名,就能讓別人基本知道該變量的含義。memcpy內(nèi)存拷貝,沒(méi)有問(wèn)題;memmove,內(nèi)存移動(dòng)?錯(cuò),如果這樣理解的話(huà),那么這篇文章你就必須要好好看看了,memmove還是內(nèi)存拷貝。那么既然memcpy和memmove二者都是內(nèi)存拷貝,那二者究竟有什么區(qū)別呢?
先說(shuō)memcpy
你有沒(méi)有好好的參加過(guò)一場(chǎng)C++筆試。讓你寫(xiě)出memcpy的實(shí)現(xiàn),這是多么常見(jiàn)的筆試題啊。現(xiàn)在,拿起你的演算紙和筆;是的,是筆和紙,不是讓你在你的IDE上寫(xiě)。寫(xiě)不出來(lái)?看下面吧:
memcpy的實(shí)現(xiàn)很簡(jiǎn)單,一般在筆試時(shí),出現(xiàn)寫(xiě)源碼的題目,無(wú)非就是需要注意以下幾點(diǎn):
1.確定函數(shù)原型;
2.判斷參數(shù)合法性;
3.邏輯實(shí)現(xiàn)(考慮各種情況,統(tǒng)稱(chēng)邏輯實(shí)現(xiàn));
4.錯(cuò)誤處理。
當(dāng)然了,我的這個(gè)沒(méi)有錯(cuò)誤處理,也不需要錯(cuò)誤處理。上面,我寫(xiě)出了memcpy的實(shí)現(xiàn)源碼,實(shí)現(xiàn)原理如下圖所示:

這樣下去,上面的代碼會(huì)運(yùn)行的很好,如果出現(xiàn)下面的情況呢?

i、n、k的內(nèi)存和J、e、l的內(nèi)存地址重合了,現(xiàn)在再使用上面的代碼進(jìn)行copy時(shí),會(huì)出現(xiàn)什么問(wèn)題呢?你有沒(méi)有想過(guò)這個(gè)問(wèn)題。如果沒(méi)有,那就現(xiàn)在想想,不急著閱讀下面的內(nèi)容。
然后,我再留一個(gè)問(wèn)題,上面的代碼中,為什么都需要將void *轉(zhuǎn)換成char *呢?比如:
可以留言回答哦。
再說(shuō)memmove
memmove也是用來(lái)實(shí)現(xiàn)內(nèi)存的直接拷貝的。說(shuō)起這個(gè)命名,我個(gè)人覺(jué)的多少還是有點(diǎn)坑的。既然memmove也是用來(lái)內(nèi)存數(shù)據(jù)移動(dòng)的,那就先來(lái)看看memmove的實(shí)現(xiàn)源碼。
從源碼看,memmove的確比memcpy復(fù)雜一些;再仔細(xì)一看,多了些什么?哦,多了一個(gè)else分支,而正是這個(gè)else分支,就處理了當(dāng)src和dest的內(nèi)存重合的問(wèn)題。
memcpy和memmove的比較
從實(shí)現(xiàn)源碼中的確能看出一些貓膩,當(dāng)出現(xiàn)了src和dest的內(nèi)存有重合的時(shí)機(jī)時(shí),memmove的處理規(guī)則是從后往前進(jìn)行copy。當(dāng)然了,重合的問(wèn)題,需要考慮的以下兩種場(chǎng)合。

如圖所示,當(dāng)出現(xiàn)(1)對(duì)應(yīng)的情況時(shí),就需要先從src的頭部開(kāi)始復(fù)制;也就是memmove源碼中的if分支,這部分源碼和memcpy的實(shí)現(xiàn)是一致的;當(dāng)出現(xiàn)(2)對(duì)應(yīng)的情況時(shí),就需要先從src的尾部開(kāi)始復(fù)制,防止出現(xiàn)了覆蓋現(xiàn)象。這就是memmove比memcpy多的一個(gè)考慮點(diǎn),所以說(shuō),在實(shí)際使用時(shí),使用memmove是比memcpy更安全的。
總結(jié)
總結(jié)到了這里,我覺(jué)的我已經(jīng)把問(wèn)題說(shuō)清楚了。你說(shuō)呢?如果你還有什么好的想法,歡迎你和我分享。
新聞熱點(diǎn)
疑難解答