C++ memset 和 memcpy
(1) Memset
原型: extern void *memset(void *buffer, int c, int count);
用法: #include <string.h>
功能: 把buffer所指記憶體區域的前count個位元組設定成字元 c。
說明: 返回指向buffer的指標。用來對一段記憶體空間全部設定為某個字元
例如:
char a[10];
memset(a, '\0', sizeof(a));
memset可以方便的清空一個結構型別的變數或陣列。
如:
struct _test{ char s[10];
int x;
int y;
};
變數 struct _test st;
(1)一般清空st的方法如下:
st.s[0] = '\0'; st.x =0; st.y =0;
(2) 用memset方法如下:
memset(&st,0,sizeof(struct _test));
陣列: struct _test st[10];
memset(st,0,sizeof(struct _test)*10); //清空方法
//memset 原始碼的實現 C語言
#include <mem.h>
void* memset(void* s, int c, size_t n)
{
unsigned char* p = (unsigned char*) s;
while (n > 0)
{
*p++ = (unsigned char) c;
--n;
}
return s;
}
(2)memcpy
原型:extern void *memcpy(void*dest,void*src,unsignedintcount);
用法: #include <string.h>
功能: 由src所指記憶體區域複製count個位元組到dest所指記憶體區域。
說明: src和dest所指記憶體區域不能重疊,函式返回指向dest的指標.可以拿它拷貝任何資料型別的物件。
例如:
char a[10] ;
memcpy(b, a, sizeof(b)); /*注意如果用sizeof(a),會造成b的記憶體地址溢位*/
(3) Strcpy
原型: extern char *strcpy(char *dest,char *src);
用法: #include <string.h>
功能: 把src所指由NULL結束的字串複製到dest所指的陣列中。
說明: src和dest所指記憶體區域不可以重疊且dest必須有足夠的空間來容納 src的字串.返回指向dest的指標。
例如:
char a[100],b[50];
strcpy(a,b);
如用 strcpy(b,a);要注意a中的字串長度(第一個‘\0’之前)是否超過50位,如超過,則會造成b的記憶體地址溢位。
假如有如下程式碼,請問輸出為多少?
#include "stdio.h"
main() {
char dest[3];
char str[6]="Hello";
strcpy(dest,str);
printf("%s\n",dest);
}
編譯輸出如下結果:
Hello //沒有輸出亂碼,有點怪怪的為什麼?
分析:
1>str中字串的長度大於dest 的記憶體長度3.為什麼str字串還能完拷貝到dest 中呢?
來看看 strcpy的 原始碼實現:
char *strcpy(char *strDest,const char *strSrc)
{
assert((strDest!=NULL)&&(strSrc !=NULL)) //判斷指標是否合法,即分配記憶體,指向某塊確定區域
char *address = strDest; //記住目標地址的起始值
while((*strDest++ = *strSrc++)!='\0') //先拷貝,後判斷,這樣就不用在拷貝完了後,再加一句 NULL;
// *strDest = '\0'; -->即加一個結束符.因為字串結束已拷貝了.
return address; //返回目標首地址的值。
}
//從上面的程式碼可以看出,strcpy函式,假定strDest的記憶體空間是足夠可以放下strSrc的內容的.
//也就是說使用者,在使用strcpy函式時,應使 (strDest記憶體空間)>= (strSrc記憶體空間)
// 在呼叫 strcpy(dest,str); 時,while((*strDest++ = *strSrc++)!='\0') 沒有判斷strDest的記憶體是否夠,而是將srtSrc的內容直接拷貝到strDest,當拷到'\0'就結束.
//因此在使用printf("%s\n",dest); 時 輸出遇到'\0'時停此輸出.所以會輸出: Hello
(4) 三者區別
memset 主要應用是初始化某個記憶體空間。
memcpy 是用於copy源空間的資料到目的空間中。
strcpy 用於字串copy,遇到‘\0’,將結束。
如果理解了這些,就能知道它們的區別:
例如初始化某塊空間的時候,用到memcpy,那麼就顯得笨拙
int m[100]
memset((void*)m,0x00,sizeof(int*100); //Ok!
memcpy((void*)m,"\0\0\0\0....",sizeof(int)*100); //Not Ok
*******函式原型*******
1、 strcpy extern char *strcpy(char *dest,char *src);
#include <string.h>
功能:把src所指由NULL結束的字串複製到dest所指的陣列中
說明: src和dest所指記憶體區域不可以重疊且dest必須有足夠的空間來容納src的字串。 返回指向dest的指標
2、 memcpy extern void *memcpy(void *dest,void *src,unsigned int count);
#include <string.h>
功能:由src所指記憶體區域複製count個字串到dest所指記憶體區域.
說明:src和dest所指記憶體區域不能重疊,函式返回指向dest的指標.
3、 memset extern void *memset(void *buffer,int c,int count);
#include <string.h>
功能:把buffer所指記憶體區域的前count個位元組設定成字元c
說明:返回指向buffer的指標.
*******區別 ****************
1)memset 用來對一段記憶體空間全部設定為某個字元,一般用於在對定義的字串初始化為' '或者'\0';
例: char a[100]; memset(a,'\0',sizeof(a));
2)memcpy 是用來做記憶體拷貝,可以用來拷貝任何資料型別的物件,可以指定拷貝的資料長度;
例: char a[100],b[50];
memcpy(b,a,sizeof(b));
//注意:如果使用sizeof(a),會造成記憶體溢位
mem是一段記憶體,他的長度,必須自己記住.memcpy是見著什麼拷貝什麼。
3)strcpy 就只能拷貝字串,它遇到'\0'就結束拷貝;
例:char a[100],b[50]; strcpy(a,b);
如用strcpy(b,a)要注意a中的字串長度(第一個'\0'之前) 是否超過50,如果超過,則會造成b的 記憶體溢位.
它是不會拷貝'\0'的,所以一般還有加一個語句: *a='\0';
************使用技巧 ************************
memset 可以方便的清空一個數據結構的變數或陣列.
如: struct sample_struct {
char csName[16];
int iSeq;
int iType;
};
對於變數
struct sample_struct stTest;
一般情況下,初始化stTest的方法:
stTest.csName[0]='\0';
stTest.iSeq=0;
stTest.iType=0;
而用memset:
memset(&stTest,0,sizeof(struct sample_struct));
如果是陣列:
struct sample_struct TEST[100];
memset(TEST,0,sizeof(struct sample_struct)*100);