日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解strncpy这个函数

發布時間:2025/6/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解strncpy这个函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.不考慮內存重疊的strncpy

網上很多博客也寫了這個函數,面試也常常會遇到,但是,我發現網上的很多代碼都是有問題的,我們先看下大部分網上博客的實現: [plain]?view plain?copy
  • char?*strncpy(char?*dst,?const?char?*src,?size_t?len)??
  • {??
  • ????assert(dst?!=?NULL?&&?src?!=?NULL);??
  • ????char?*res?=?dst;??
  • ????while?(len--)??
  • ????{??
  • ????????*dst++?=?*src++;??
  • ????}??
  • ????return?res;??
  • }??

  • 看著好像沒啥問題,但是,當src的長度小于len呢?這份代碼沒有處理這個問題。當src的長度小于len時,應該如何處理?《C和指針》p179給出的答案是: “和strcpy一樣,strncpy把源字符串的字符復制到目標數組。然而,它總是正好向dst寫入len個字符。如果strlen(src)的值小于len,dst數組就用 額外的NUL字節填充到len長度,如果strlen(src)的值大于或等于len,那么只有len個字符被復制到dst中。” 注意!它的結果將不會以NUL字節結尾。(NUL即‘\0’). 由此可見,我們還需要判斷strlen(src)是否小于len,如果是,還需要在dst后面添加NUL,因此,正確的代碼應該如下: [plain]?view plain?copy
  • char?*strncpy(char?*dest,?const?char?*src,?size_t?len)??
  • {??
  • ????assert(dest?!=?NULL?&&?src?!=?NULL);??
  • ????char?*res?=?dest;??
  • ????int?offset?=?0;??
  • ????if?(strlen(src)?<?len)//src長度小于len??
  • ????{??
  • ????????offset?=?len?-?strlen(src);??
  • ????????len?=?strlen(src);??
  • ????}??
  • ??
  • ????while?(len--)??
  • ????{??
  • ????????*dest++?=?*src++;??
  • ????}??
  • ????while?(offset--)??
  • ????{??
  • ????????*dest++?=?'\0';??
  • ????}??
  • ????return?res;??
  • }??

  • ? 使用這個函數,尤其需要注意,不要出現len>strlen(dst)的情況,如果len>strlen(dst),那么會破壞dst后面的內存: 我們假設前面紅色部分是dst,然后strncpy(dst,src,10);那么后面黃色部分的內存就被破壞了。strncpy是不負責檢測len是否大于dst長度的。 總的來說,strncpy總是復制len個字符到dst指向的內存!!! 所以,還會出現下面的情況: [plain]?view plain?copy
  • char?message[]?=?"abcd";??
  • strncpy(message,?"abcde",5);??
  • cout?<<?message;??
  • 輸出是abcde燙燙燙燙燙燙燙燙燙燙燙燙燙燙 ?(結果不唯一)
    message的內存是有5個字節的,但是將abcde拷貝過去時,最后面的‘\0’被覆蓋了,strncpy并不會負責添加‘\0’到dst結尾,因此,輸出該字符串是,會在e字符后面一直找到‘\0’才結束,因此就會出現亂碼。

    2.考慮內存重疊的strncpy

    面試中經常會遇到讓你寫一個能夠處理內存重疊的strncpy,標準庫中的strncpy是不考慮內存重疊的,如果出現內存重疊,結果將是未定義的。 網上的很多博客也有這個代碼的實現,其實很多也是有問題的,沒有考慮src長度小于len的問題: [plain]?view plain?copy
  • char?*strncpy(char?*dst,?const?char?*src,?size_t?len)??
  • {??
  • ????assert(dst?!=?NULL?&&?src?!=?NULL);??
  • ????char?*res?=?dst;??
  • ????if?(dst?>=?src?&&?dst?<=?src?+?len?-?1)//重疊,從后向前復制??
  • ????{??
  • ????????dst?=?dst?+?len?-?1;??
  • ????????src?=?src?+?len?-?1;??
  • ????????while?(len--)??
  • ????????????*dst--?=?*src--;??
  • ????}??
  • ????else??
  • ????{??
  • ????????while?(len--)??
  • ????????????*dst++?=?*src++;??
  • ????}??
  • ????return?res;??
  • }??

  • ? 那么,如果要處理內存重疊,該怎么辦?如果內存重疊和src的長度小于len這兩種情況同時出現,又如何處理? 見圖,假設紅色部分為src,黃色為dst。如果出現內存重疊,我們很容易想到:從后往前拷貝。如果src的長度小于len,則在后面補NUL。 [plain]?view plain?copy
  • char?*strncpy(char?*dst,?const?char?*src,?size_t?len)??
  • {??
  • ????assert(dst?!=?NULL?&&?src?!=?NULL);??
  • ????char?*res?=?dst;??
  • ????int?offset?=?0;??
  • ????char?*tmp;??
  • ????if?(strlen(src)?<?len)//src長度小于len??
  • ????{??
  • ????????offset?=?len?-?strlen(src);??
  • ????????len?=?strlen(src);??
  • ????}??
  • ??
  • ????if?(dst?>=?src?&&?dst?<=?src?+?len?-?1)//重疊,從后向前復制??
  • ????{??
  • ????????dst?=?dst?+?len?-?1;??
  • ????????src?=?src?+?len?-?1;??
  • ????????tmp?=?dst;??
  • ????????while?(len--)??
  • ????????????*dst--?=?*src--;??
  • ????}??
  • ????else??
  • ????{??
  • ????????while?(len--)??
  • ????????????*dst++?=?*src++;??
  • ????????tmp?=?dst;??
  • ????}??
  • ????while?(offset--)??
  • ????{??
  • ????????*tmp++?=?'\0';??
  • ????}??
  • ????return?res;??
  • }??

  • 那么,如果len的值大于dst的值,就會破壞dst后面的內存空間,這應該是要避免的。 最后,我們看一個有意思的東西:(此處strncpy是考慮內存重疊的版本) message的長度增加了0.0 ?當然 ?,它后面的內存被破壞了,這可能帶來嚴重的后果。 最后,使用strncpy時,最好自動添加‘\0’在結尾: [plain]?view plain?copy
  • char?buffer[BSIZE];??
  • .??
  • .??
  • strncpy(buffer,name,BSIZE);??
  • buffer[BSIZE-1]='\0';??
  • 總結

    以上是生活随笔為你收集整理的深入理解strncpy这个函数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。