Mem系列函數與Str系列函數總結(一)   memcpy/memccpy/memmove與strcpy/strcnpy

   Mem系列函數通常處理內存內容,而Str通常處理字符串,這倆個家族系列函數經常會使用,po主應屆生一枚,總是會遇到各種不熟,乾脆在此總結下,方便日後查閱,爲了能夠更好地體現出兩家族函數的異同,將採用對比的形式一一列出:


------------------------------------- 分界線------------------------------------

-------------------------------------------------------------------------------

一 拷貝函數


函數名稱: memcpy

函數原型:void *memcpy(void *dest, const void *src,size_t n);

函數功能:內存拷貝;將src指向內存地址的連續N個指針位置的內容拷貝至dest指針指向的位置

函數返回:無

參數說明:dest — 目的內存空間指針

            src — 源內存空間指針

             n  — 拷貝指針位置個數


使用方法


# include <memory>
# include <iostream>
# include <string>
void main()
{
    char * src = "Hello Frankie World !";
    char * dest = new char[50];
    memset(dest,0,50);
    memcpy(dest,src,7);
   std::cout<<"dset值爲:"<<std::endl;
   Out(dest);
                                                                                                                                                                                                                                                                                                                                                                         
}

結果

wKiom1MdshqiVjr1AAATmvcwDww537.jpg




------------------------------------- 分界線------------------------------------

-------------------------------------------------------------------------------



函數名稱:memccpy

函數原型:void * memccpy(void *dest, void *src, unsigned char c, unsigned int count);

函數功能:由src所指內存區域複製不多於count個字節到dest所指內存區域,如果第一次遇到字符c則停止複製

函數返回:如果c沒有被複制,則返回NULL,否則,返回字符c 後面緊挨一個字符位置的指針


使用:

int  main()
{
    char *src = "Welcome to Frankie world! sorry, I love you!";
    char dest[80];
    char *ptr;
    ptr = (char *)memccpy(dest, src, '!', strlen(src));
    if (ptr)
    {
        *ptr = '\0';
        printf("The character was found: %s\n", dest);
    }
    else
        printf("The character wasn't found\n");
    return 0;
                                                                                                                                                                                                                        
}

結果:

wKiom1MhZsbgWSCTAAA0Dw-O_6A425.jpg



說明:

memccpy只會碰到一個指定字符就停止複製



------------------------------------- 分界線------------------------------------

-------------------------------------------------------------------------------

函數名稱:memmove

函數原型:void *memmove( void* dest, const void* src, size_t count );

函數功能:由src所指內存區域複製count個字節到dest所指內存區域。


說明

   函數memcpy()從source指向的區域向dest指向的區域複製count個字符,如果兩數組重疊,不定義該函數的行爲。  

   而memmove(),如果兩函數重疊,賦值仍正確進行。

   memcpy函數假設要複製的內存區域不存在重疊,如果你能確保你進行復制操作的的內存區域沒有任何重疊,可以直接用memcpy,且其效率會比memcpy高;  

如果你不能保證是否有重疊,爲了確保複製的正確性,你必須用memmove


memmove的處理措施

(1)當源內存的首地址等於目標內存的首地址時,不進行任何拷貝

(2)當源內存的首地址大於目標內存的首地址時,實行正向拷貝

(3)當源內存的首地址小於目標內存的首地址時,實行反向拷貝


(1)內存低端 <-----s-----> <-----d-----> 內存高端 start at end of s
(2)內存低端 <-----s--<==>--d----->      內存高端 start at end of s
(3)內存低端 <-----sd----->              內存高端 do nothing
(4)內存低端 <-----d--<==>--s----->      內存高端 start at beginning of s
(5)內存低端 <-----d-----> <-----s-----> 內存高端 start at beginning of s



------------------------------------- 分界線------------------------------------

-------------------------------------------------------------------------------

函數名稱:strcpy

函數原型:char *strcpy(char* dest, const char *src);

函數功能:字符串拷貝;把從src地址開始且含有\0結束符的字符串複製到以dest開始的地址空間

函數返回:dest字符串指針

相關說明: src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串。


使用方法

# include <memory>
# include <iostream>
# include <string>
void main()
{
    char * src = "Hello Frankie World !";
    char * dest = new char[50];
                                                                                                                                                                                                                                                                                                                                                                   
    char * dest1 = new char[50];
                                                                                                                                                                                                                                                                                                                                                                   
    memset(dest,0,50);
                                                                                                                                                                                                                                                                                                                                                                   
    memset(dest1,0,50);
                                                                                                                                                                                                                                                                                                                                                                   
    memcpy(dest,src,7);
                                                                                                                                                                                                                                                                                                                                                                   
    strcpy(dest1,src);
                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                  
   std::cout<<"dset值爲:"<<std::endl;
   Out(dest);
                                                                                                                                                                                                                                                                                                                                                                  
   std::cout<<"dset1值爲:"<<std::endl;
   Out(dest1);
                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                   
}

結果:


wKioL1MdtKLQ7PsPAAAoGCdanj4732.jpg


memcpy與strcpy區別

1、

   複製的內容不同。strcpy只能複製字符串,而memcpy可以複製任意內容,例如字符數組、整型、結構體、類等。

2、

   複製的方法不同。strcpy不需要指定長度,它遇到被複制字符的串結束符"\0"才結束,所以容易溢出。memcpy則是根據其第3個參數決定複製的長度。

3、

   用途不同。通常在複製字符串時用strcpy,而需要複製其他類型數據時則一般用memcpy



------------------------------------- 分界線------------------------------------

-------------------------------------------------------------------------------

補充:

函數名稱: strncpy

函數原型:char * strncpy( char *dest, char *src, size_t num );

函數功能

   複製src中的內容(字符,數字、漢字....)到dest,複製多少由num的值決定,返回指向dest的指針。如果遇到null字符('\0'),且還沒有到num個字符時,就用(num - n)(n是遇到null字符前已經有的非null字符個數)個null字符附加到destination。注意:並不是添加到destination的最後,而是緊跟着由source中複製而來的字符後面

函數返回: dest指針


使用方法

# include <memory>
# include <iostream>
# include <string>
void main()
{
    char * src = "Hello Frankie World !";
    char * dest = new char[50];
                                                                                                                                                                                                                                                                                                                                                            
    char * dest1 = new char[50];
                                                                                                                                                                                                                                                                                                                                                            
    char * dest2 = new char[50];
                                                                                                                                                                                                                                                                                                                                                                             
    memset(dest,0,50);
                                                                                                                                                                                                                                                                                                                                                            
    memset(dest1,0,50);
                                                                                                                                                                                                                                                                                                                                                            
    memset(dest2,0,50);
                                                                                                                                                                                                                                                                                                                                                            
    memcpy(dest,src,7);
                                                                                                                                                                                                                                                                                                                                                            
    strcpy(dest1,src);
                                                                                                                                                                                                                                                                                                                                                            
    strncpy(dest2,src,7);
                                                                                                                                                                                                                                                                                                                                                           
   std::cout<<"dset值爲:"<<std::endl;
   Out(dest);
                                                                                                                                                                                                                                                                                                                                                           
   std::cout<<"dset1值爲:"<<std::endl;
   Out(dest1);
                                                                                                                                                                                                                                                                                                                                                           
   std::cout<<"dset2值爲:"<<std::endl;
   Out(dest2);
}

結果

wKiom1MdtlShY-Y6AAA4yO4cz1Y089.jpg


相關說明:

如果n > dest串長度,dest棧空間溢出產生崩潰異常。

否則:

1)

src串長度<=dest串長度,(這裏的串長度包含串尾NULL字符)

如果n<src串長度,src的前n個字符複製到dest中。但是由於沒有NULL字符,所以直接訪問dest串會發生棧溢出的異常情況。

如果n = src串長度,與strcpy一致。

如果n >src串長度,src串存放於dest字串的[0,src串長度],dest串的(src串長度, dest串長度]處存放NULL。

2)

src串長度>dest串長度

如果n =dest串長度,則dest串沒有NULL字符,會導致輸出會有亂碼。如果不考慮src串複製完整性,可以將dest 最後一字符置爲NULL。

3)

綜上,一般情況下,使用strncpy時,建議將n置爲dest串長度(除非你將多個src串都複製到dest數組,並且從dest尾部反向操作),複製完畢後,爲保險起見,將dest串最後一字符置NULL,避免發生在第2)種情況下的輸出亂碼問題。當然嘍,無論是strcpy還是strncpy,保證src串長度<dest串長度纔是最重要的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章