1.函數原型:
extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include <string.h>
功能:由src所指內存區域復制count個字節到dest所指內存區域。
說明:src和dest所指內存區域不能重疊,函數返回指向dest的指針。
例子:
// memcpy.c
#include<stdio.h>
#include<string.h>
int main()
{
char*s="Golden Global View";
chard[20];
clrscr();
memcpy(d,s,strlen(s));
d[strlen(s)]='\0';//因為從d[0]開始復制,總長度為strlen(s),d[strlen(s)]置為結束符
printf("%s",d);
getchar();
return0;
}
注意:
1.source和destin所指內存區域不能重疊,函數返回指向destin的指針。
2.與strcpy相比,memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個字節。
memcpy用來做內存拷貝,你可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度;
例:
char a[100], b[50];
memcpy(b, a,sizeof(b)); //注意如用sizeof(a),會造成b的內存地址溢出。
strcpy就只能拷貝字符串了,它遇到'\0'就結束拷貝;例:
char a[100], b[50];
strcpy(a,b);
3.如果目標數組destin本身已有數據,執行memcpy()后,將覆蓋原有數據(最多覆蓋n)。如果要追加數據,則每次執行memcpy后,要將目標數組地址增加到你要追加數據的地址。
//注意,source和destin都不一定是數組,任意的可讀寫的空間均可。
程序例子
example1:
作用:將s中的字符串復制到字符數組d中。
//memcpy.c
#include<stdio.h>
#include<string.h>
int main()
{
char*s="Golden Global View";
chard[20];
clrscr();
memcpy(d,s,strlen(s));
d[strlen(s)]='\0';//因為從d[0]開始復制,總長度為strlen(s),d[strlen(s)]置為結束符
printf("%s",d);
getchar();
return0;
}
輸出結果:
Golden Global View
example2:
作用:將s中第14個字符開始的4個連續字符復制到d中。(從0開始)
#include<string.h>
int main()
{
char*s="Golden Global View";
chard[20];
memcpy(d,s+14,4);//從第14個字符(V)開始復制,連續復制4個字符(View)
//memcpy(d,s+14*sizeof(char),4*sizeof(char));也可
d[4]='\0';
printf("%s",d);
getchar();
return0;
}
輸出結果:
View
example3:
作用:復制后覆蓋原有部分數據
#include<stdio.h>
#include<string.h>
int main(void)
{
charsrc[] = "******************************";
chardest[] = "abcdefghijlkmnopqrstuvwxyz0123as6";
printf("destinationbefore memcpy: %s\n", dest);
memcpy(dest,src, strlen(src));
printf("destinationafter memcpy: %s\n", dest);
return0;
}
輸出結果:
destinationbefore memcpy:abcdefghijlkmnopqrstuvwxyz0123as6
destinationafter memcpy: ******************************as6
另外,可以拷貝任何類型的對象,因為函數的參數類型是void *(未定義類型指針),也就是說傳進去的實參可以是int *,short *,char *等等,
但是由於函數拷貝的過程是一個字節一個字節的拷貝的,所以實際操作的時候要把void *強制轉化為char *,這樣在指針加的時候才會保證每次加一個字節。
函數源代碼實現:
void *memcpy1(void *desc,const void * src,size_t size)
{
if((desc == NULL) && (src == NULL))
{
return NULL;
}
unsigned char *desc1 = (unsigned char*)desc;
unsigned char *src1 = (unsigned char*)src;
while(size-- >0)
{
*desc1 = *src1;
desc1++;
src1++;
}
return desc;
}
int _tmain(int argc, _TCHAR* argv[])
{
int dest[2] = {0};
const char src[5] = "1234";
//printf(src);
memcpy1(dest,src,sizeof(src));
//*(dest+5) = '/0';
printf((char *)dest);
int m = -1;
return 0;
}
(1)void* 一定要返回一個值(指針),這個和void不太一樣!
(2)首先要判斷指針的值不能為空,desc為空的話肯定不能拷貝內存空間,src為空相當於沒有拷貝;所以之間return掉;
(3)""空串是指內容為0,NULL是0,不是串;兩個不等價;
(4)int dest[2] = {0};這是對int 類型的數組初始化的方法;如果是char類型,就用char a[5] = "1234"; 注意數組下標要多於實際看到的字符數,因為還有'\0'
(5)printf((char *)dest);這句話,是把 char 類型 src 傳到 int 類型的 dest的內存強制轉化成char類型,然后打印出來;
因為直接看int類型的dest是看不到里面的內容的;因為有unsigned char *desc1 = (unsigned char *)desc;所以字符可以傳到dest里面保存起來,dest所指向的內存長度4個字節,強制轉化為char 就是把四個字節分成一個一個的字節,這樣就可以看到一個個字符了,如果定義成char dest[5] = "1234";就不用轉化;
(6)memcpy1(dest,src,sizeof(src));注意里面的sizeof(src),這個是包括字符串的結束符'/0'的;所以不用擔心printf(dest);
但是如果用memcpy1(dest,src,4);沒有'/0'就要 *(dest+5) = '/0';這樣保證是一個完整的字符串;
(7)如果初始化的時候:
char dest[1024] = "12345666";//{0};
const char src[5] = "3333";
那么拷貝的時候,如果用memcpy1(dest,src,sizeof(src));則printf(dest);出來是3333
如果memcpy1(dest,src,4);則printf(dest);出來是33335666;因為上面的sizeof(src),包含'/0',所以拷貝過去的字符串以'/0'結束,就只有3333,而如果傳4個字符,'/0'是第五個字符,那就遇到dest[1024] 的'/0'結束,所以是33335666
字符串的'\0'問題一定要注意啊!!!