1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
      C語言之memcpy函數(shù)

      昨天自己動(dòng)手實(shí)現(xiàn)memcpy這個(gè)函數(shù),用一個(gè)例程試了一下,結(jié)果正確,滿心歡心,可是有些地方想不明白,于是百度了一下,結(jié)果自己寫的函數(shù)簡(jiǎn)直無法直視。

      為界首等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及界首網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為做網(wǎng)站、網(wǎng)站設(shè)計(jì)、界首網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

      覺得還是寫個(gè)總結(jié),以示教訓(xùn)。

      先貼上我自己的函數(shù):

      [cpp] view plain copy C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. char *mymemcpy(char *dest, const char * src, int n)  

      2. {  

      3.         char *pdest;  

      4.         char *psrc;  

      5.         pdest = dest;  

      6.         psrc = src;  

      7.   

      8.         for(n; n>0; n--)  

      9.         {  

      10.                 *pdest = *psrc;  

      11.                 pdest++;  

      12.                 psrc++;  

      13.         }  

      14. }  

      我這個(gè)程序只能是在非常理想的條件下才能完成復(fù)制任務(wù),一旦參數(shù)有誤,那么就會(huì)運(yùn)行出錯(cuò);另外沒有返回值,而是直接將dest指針作為了返回型參數(shù)。

      另一點(diǎn)需要注意:在函數(shù)體中我另外聲明了兩個(gè)指針,分別指向dest和src,我是這樣想的:由于循環(huán)中要移動(dòng)指針,為了不影響主程序中實(shí)參指針的位置,所以我認(rèn)為需要重新定義兩個(gè)指針。后來我發(fā)現(xiàn),我這樣想是錯(cuò)誤的,指針變量實(shí)質(zhì)上也是變量,指針作為形參,那么這個(gè)指針也是實(shí)實(shí)在在存在的,那么在函數(shù)中改變這個(gè)形參指針的位置并不會(huì)影響主程序中實(shí)參指針的位置。所以在這個(gè)函數(shù)中,沒必要重新聲明兩個(gè)指針,最好是在返回值中返回一個(gè)指向dest的指針就夠了。

      我會(huì)犯上述這個(gè)錯(cuò)誤,應(yīng)該是受了“地址傳參”和“值傳參”的影響。由于地址傳參太過于強(qiáng)調(diào)函數(shù)可以改變主程序中的數(shù)據(jù)內(nèi)容,以至于讓我把形參指針和實(shí)參指針等同起來了。實(shí)質(zhì)上形參指針變量位置的改變并不會(huì)影響實(shí)參指針的位置。

      重要的內(nèi)容寫前面,

      自己總結(jié)該函數(shù)的幾個(gè)要點(diǎn):

      1、參數(shù)判斷:對(duì)參數(shù)的合法性進(jìn)行判斷

      2、聲明中間變量:由于要返回目的指針,所以需要保留目的首地址;最好是不要破壞形參,設(shè)置臨時(shí)變量替換

      3、void *類型:要注意dest和src的類型可能不同,進(jìn)而造成dest++ src++不匹配的問題,先強(qiáng)制類型轉(zhuǎn)換

      4、void 類型做右值:void類型變量或是返回值為void類型的函數(shù),一旦做右值編譯出錯(cuò)

      5、指針形參:即上面提到的,指針變量本質(zhì)仍是指針,形參指針位置的改變不會(huì)影響實(shí)參指針的位置

      下面是參考網(wǎng)友的一些總結(jié),紅色字體為本人批注:

      memcpy實(shí)現(xiàn)內(nèi)存拷貝,根據(jù)這個(gè)問題,我們可以提取出下面幾點(diǎn):

      1.可以拷貝任何數(shù)據(jù),數(shù)據(jù)類型不能受限

      2.源數(shù)據(jù)不能被改變

      通過上面兩點(diǎn)可以確定函數(shù)原型為void *memcpy(void *dest, const void *src),現(xiàn)在分析一下這些足夠了嗎?這個(gè)函數(shù)拷貝什么時(shí)候結(jié)束,當(dāng)時(shí)我就用了這個(gè)函數(shù)原型,由于是拷貝的任意數(shù)據(jù),所以不能指定一個(gè)明確的結(jié)束標(biāo)志,既然這樣那么只有明確的指定拷貝的大小才可以.所以函數(shù)原型變成這樣void *memcpy(void *dest, void *src, size_t count);好吧,函數(shù)原型既然已經(jīng)確認(rèn)了,剩下的應(yīng)該就是寫函數(shù)了,先等等,先別急著寫函數(shù),實(shí)際上對(duì)于C語言的開發(fā)者來說,重要的不是函數(shù)功能的實(shí)現(xiàn),重要的是函數(shù)出錯(cuò)時(shí)的處理,如果你用的是Java或者C#大不了拋個(gè)異常出來,軟件崩潰一下,不會(huì)對(duì)其他造成任何影響;C這東西弄不好會(huì)把整個(gè)系統(tǒng)弄癱瘓,所謂”兵馬未動(dòng),糧草先行”,我么還是先考慮考慮出錯(cuò)的問題吧!我們根據(jù)函數(shù)原型來分析,

      void *memcpy(void *dest, const void *src, size_t count);

      1.空指針的問題,如果dest、src兩者或者兩者之一為NULL,那么自然能沒得完了;

      2.拷貝大小count為小于等于0的值,自然也是不正確的;

      3.目標(biāo)有沒有足夠的大小容納源數(shù)據(jù),這個(gè)我們?cè)诤瘮?shù)內(nèi)部似乎也無法進(jìn)行保證,但是我們自己也要想到

      4.內(nèi)存地址有沒有重疊,這個(gè)我們暫時(shí)不考慮了。

      有了上面的提示寫起來自然比較簡(jiǎn)單了

      [cpp] view plain copy C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. #include   

      2. void *memcpy(void *dest, const void *src, size_t count)  

      3. {  

      4.     if (NULL == dest || NULL == src || count <= 0)  

      5.         return NULL;  

      6.     while (count--)  

      7.         *dest++ = *src++;  

      8.     return dest;  

      9. }  

      上面這段代碼在Linux中使用gcc編譯是沒錯(cuò)的,但是會(huì)有警告,所以改成這樣:
      (注意,上述代碼我在測(cè)試時(shí),不僅有警告還有一個(gè)錯(cuò)誤:error: invalid use of void expression,這是因?yàn)関oid型的變量或者是函數(shù)返回值被使用了。使用下面這段代碼是可以通過編譯的:)

      [cpp] view plain copy C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. #include   

      2. void *memcpy(void *dest, const void *src, size_t count)  

      3. {  

      4.     if (NULL == dest || NULL == src || count <= 0)  

      5.         return NULL;  

      6.     while (count--)  

      7.         *(char *)dest++ = *(char *)src++;  

      8.     return dest;  

      9. }  


      OK,也就這樣了,要是面試官再問起內(nèi)存重疊的問題,你再和他侃侃.我的面試算是泡湯了.

      總結(jié):不要著急慢慢來,根據(jù)需求推出原型,根據(jù)原型推斷問題,這算是個(gè)教訓(xùn)吧!!!

      補(bǔ)充:

      在這里非常感謝博客園的求道于盲  這位好心的網(wǎng)友指出了我程序中的兩個(gè)錯(cuò)誤,再次感謝.

      1.返回了一個(gè)++過的指針

      2.size_t是無符號(hào)類型的,size_t的定義為:typedef unsigned int size_t;

      所以count<=0,只會(huì)判斷==0的情況,如果傳入-1,會(huì)產(chǎn)生一個(gè)很大的無符號(hào)整型.

      希望別人注意,改過的程序如下:

      [cpp] view plain copy C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. void *memcpy(void *dest, const void *src, int count)  

      2. {  

      3.     void *ptr = dest;  

      4.     if (NULL == dest || NULL == src || count <= 0)  

      5.     return NULL;  

      6.    

      7.     while (count--)  

      8.         *(char *)dest++ = *(char *)src++;  

      9.    

      10.     return ptr;  

      11. }  




      本文通過匯總一些網(wǎng)上搜集到的資料,總結(jié)c語言中的memcpy實(shí)現(xiàn)

      背景

      想必大多數(shù)人在面試時(shí)被要求寫 memcpy的實(shí)現(xiàn),很不幸,我也吃過這個(gè)虧(這種題要是寫的一塌糊涂后面完全沒戲),所以還是得提前準(zhǔn)備一下,不然就只能呵呵了。先來看看一段錯(cuò)誤的示范: 找茬:)

      [cpp] view plain copy  C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. void * memcpy(void *dest, const void *src, unsigned int count);  

      2. {  

      3.     if ((src == NULL) || (dest == NULL))  

      4.         return;  

      5.       

      6.     while (count--)  

      7.         *dest++ = *src++;  

      8.           

      9.     return dest;  

      10. }  

      dest都指到哪里去了?怎么著也得備份一下dest的值,好讓函數(shù)返回的指針是從頭開始的

      考慮一下指針類型,如果dest和src的指針類型不一樣,不能直接++賦值. 例如: int* p和 char*q, p++指針的值是4個(gè)4個(gè)加(0,4,8),q++是1個(gè)1個(gè)加(0,1,2,3,4)

      第二版 - 定義兩個(gè)臨時(shí)變量,不要直接++ dest和src,并且指明指針類型char *

      [cpp] view plain copy  C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. void *memcpy(void *dest, const void *src, size_t count)  

      2. {  

      3.  char *tmp = dest;  

      4.  const char *s = src;  

      5.    

      6.  while (count--)  

      7.   *tmp++ = *s++ ;  

      8.     

      9.  return dest;  

      10. }  

      能否改進(jìn)? src和dest都強(qiáng)制轉(zhuǎn)換成char*類型的指針,那么copy一定是一個(gè)字節(jié)一個(gè)字節(jié)的完成?那么第三版來了

      [cpp] view plain copy  C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. void * memcpy(void *dst,const void *src,size_t num)  

      2. {  

      3.     int nchunks = num/sizeof(dst);   /*按CPU位寬拷貝*/  

      4.     int slice =   num%sizeof(dst);   /*剩余的按字節(jié)拷貝*/  

      5.       

      6.     unsigned long * s = (unsigned long *)src;  

      7.     unsigned long * d = (unsigned long *)dst;  

      8.       

      9.     while(nchunks--)  

      10.         *d++ = *s++;  

      11.           

      12.     while (slice--)  

      13.         *((char *)d++) =*((char *)s++);  

      14.           

      15.     return dst;  

      16. }  


      看著沒什么問題了,可是如果dst和src地址不對(duì)齊,copy效率豈不降低? 是否需要先處理一下地址不對(duì)齊的情況?

      再來看看dest和src地址有重疊的情況

      內(nèi)存重疊問題是指目的地址的內(nèi)存空間的首地址,包含在源內(nèi)存空間中,這兩段內(nèi)存空間有了交集,因而在使用memcpy進(jìn)行內(nèi)存復(fù)制操作時(shí),這段重疊的內(nèi)存空間會(huì)被破壞.這種情況在應(yīng)用程序級(jí)代碼中一般不會(huì)出現(xiàn)的,而在驅(qū)動(dòng)或內(nèi)核級(jí)代碼中要十分小心,盡量使用memmove函數(shù).

      memcpy對(duì)內(nèi)存空間有要求的,dest和src所指向的內(nèi)存空間不能重疊,否則復(fù)制的數(shù)據(jù)是錯(cuò)誤的.下面具體講解一下這個(gè)錯(cuò)誤是如何產(chǎn)生的.

      如果內(nèi)存空間布局入下圖所示:

                                                   C語言之memcpy函數(shù)

      雖然原來的數(shù)據(jù)不再是原來的數(shù)據(jù)(dest+size>=src),但拷貝的數(shù)據(jù)是原來的數(shù)據(jù),使用memcpy函數(shù)可以得到正確的結(jié)果.因此,在使用memcpy這個(gè)函數(shù)之前,還需要做一個(gè)判斷,如果dest<=src你才能使用這個(gè)函數(shù)不過完全沒有必要, 解決辦法,從高地址向地地址copy

      實(shí)例

      [cpp] view plain copy  C語言之memcpy函數(shù)C語言之memcpy函數(shù)

      1. void *memcpy(void *dest, const void *src, size_t count)  

      2. {  

      3.  char *d;  

      4.  const char *s;  

      5.    

      6.  if (dest > (src+size)) || (dest < src))  

      7.     {  

      8.     d = dest;  

      9.     s = src;  

      10.     while (count--)  

      11.         *d++ = *s++;          

      12.     }  

      13.  else /* overlap */  

      14.     {  

      15.     d = (char *)(dest + count - 1); /* offset of pointer is from 0 */  

      16.     s = (char *)(src + count -1);  

      17.     while (count --)  

      18.         *d-- = *s--;  

      19.     }  

      20.     

      21.  return dest;  

      22. }  

      memcpy是把src指向的對(duì)象中的size個(gè)字符拷貝到dest所指向的對(duì)象中,返回指向結(jié)果對(duì)象的指針. 

      memmove也是把src指向的對(duì)象中的size個(gè)字符拷貝到dest所指向的對(duì)象中,返回指向結(jié)果對(duì)象的指針,但這兩個(gè)函數(shù)在處理內(nèi)存區(qū)域重疊的方式不同.

      注意memmove這個(gè)函數(shù)名稱中有"move"這個(gè)單詞,而實(shí)際上src處的數(shù)據(jù)仍然還在,并沒有真的被"移動(dòng)"了!這個(gè)函數(shù)名稱有它的歷史原因,是因?yàn)橛辛薽emcpy函數(shù)后,發(fā)現(xiàn)這個(gè)函數(shù)有問題,又發(fā)明了另一個(gè)沒有問題的memcpy函數(shù),但為了保證兼容性依然保留了memcpy函數(shù),而將新版本的memcpy函數(shù)改名為memmove函數(shù).


      總結(jié)

      1. 不要破壞傳進(jìn)來的形參,定義新的臨時(shí)變量來操作

      2.考慮指針的類型,不同類型的指針不能直接++賦值

      3.overlap情況下需要從高地址處向前copy


      分享標(biāo)題:C語言之memcpy函數(shù)
      分享網(wǎng)址:http://www.ef60e0e.cn/article/pgsjei.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        余庆县| 麦盖提县| 桐梓县| 龙游县| 石台县| 平和县| 昭苏县| 乐昌市| 易门县| 梨树县| 遂昌县| 五指山市| 遵义市| 湖北省| 英山县| 雷州市| 乌海市| 贵南县| 贵定县| 辽中县| 龙海市| 东平县| 兰州市| 鸡西市| 革吉县| 公主岭市| 枣阳市| 边坝县| 曲水县| 丹棱县| 芒康县| 文化| 西乌| 南阳市| 城步| 静海县| 巨鹿县| 阳高县| 乐亭县| 阳高县| 吴旗县|