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); }
結果:
------------------------------------- 分界線------------------------------------
-------------------------------------------------------------------------------
函數名稱: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; }
結果:
說明:
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); }
結果:
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); }
結果:
相關說明:
如果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串長度纔是最重要的。