詳解C語(yǔ)言中strcpy函數(shù)與memcpy函數(shù)的區(qū)別與實(shí)現(xiàn)
字符串拷貝函數(shù)(strcpy)
函數(shù)原型

由圖可知,strcpy的形參是(目的地址,來(lái)源地址),返回值為char *。
應(yīng)用實(shí)例
我們將一個(gè)存放“abcdefg”的字符數(shù)組arr的內(nèi)容拷貝到字符數(shù)組brr之中。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char arr[10] = "abcdefg";
char brr[10] = { 0 };
strcpy(brr, arr);
printf("%s", brr);
return 0;
}
缺點(diǎn)
如果不是字符類型,還能這樣拷貝嗎?

我們發(fā)現(xiàn),編譯器直接報(bào)錯(cuò)了,因?yàn)樾螀⒏鷮?shí)參不兼容。 strcpy具有局限性,只能適用于字符類型的拷貝。我們想要任意類型的都能實(shí)現(xiàn)拷貝,那怎么辦呢?我們可以使用內(nèi)存拷貝函數(shù),不管三七二十一,你在這個(gè)內(nèi)存單元上,我就把你拷貝過去,這樣便實(shí)現(xiàn)了任意類型的拷貝 。
內(nèi)存拷貝函數(shù)(memcpy)
函數(shù)原型

由圖可知,memcpy的返回類型是void*,它的形參是(目標(biāo)地址,需要復(fù)制的地址,字節(jié)大?。?/p>
應(yīng)用實(shí)例
我們依然將一個(gè)存放“abcdefg”的字符數(shù)組arr的內(nèi)容拷貝到字符數(shù)組brr之中。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char arr[10] = "abcdefg";
int ret = strlen(arr);//求出字符串的長(zhǎng)度
char brr[10] = { 0 };
memcpy(brr, arr,ret*sizeof(char));//字節(jié)數(shù)=個(gè)數(shù)*數(shù)據(jù)類型大小
printf("%s", brr);
return 0;
}
這次我們?cè)囋囌蛿?shù)組能不能拷貝過去。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int brr[10] = { 0 };
memcpy(brr, arr, 10*4);//字節(jié)數(shù)=個(gè)數(shù)*數(shù)據(jù)類型大小
for (int i = 0; i < 10; i++)
{
printf("%d ", brr[i]);
}
return 0;
}
成功了,這說明memcpy的適用范圍強(qiáng)于strcpy,那么memcpy是怎么實(shí)現(xiàn)的呢?
memcpy的模擬實(shí)現(xiàn)(my_memcpy)
實(shí)現(xiàn)樣例
void* my_memcpy(void* dest, void* src, size_t count)
{
void* ret=dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
首先觀察它形式

我們依葫蘆畫瓢,也寫出類似的函數(shù)形式。
void* my_memcpy(void* dest, void* src, size_t count)
具體實(shí)現(xiàn)
因?yàn)槲覀冇玫亩际莢oid*來(lái)接受參數(shù),目的是保證兼容性(畢竟你不知道使用者使用的時(shí)候用的是什么數(shù)據(jù)類型),但計(jì)算機(jī)不知道void*指的是什么,所以需要強(qiáng)制類型轉(zhuǎn)換。而強(qiáng)制類型轉(zhuǎn)換,換成什么類型好呢?如果我們用int型,我們知道一個(gè)int元素占4個(gè)字節(jié),那我們需要復(fù)制3個(gè)字節(jié)的東西咋辦?所以,我們用只占一個(gè)字節(jié)的char型。
*(char*)dest = *(char*)src;
在拷貝完一個(gè)字節(jié)之后,指針向后移動(dòng)一個(gè)字節(jié)
dest = (char*)dest + 1; src = (char*)src + 1;
那么我們?nèi)绾慰刂瓶截惗嗌賯€(gè)字節(jié)呢?用while搭配count就行。
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
函數(shù)運(yùn)行完了,我們隨便返回一個(gè)值就行。
return 0;
到此這篇關(guān)于詳解C語(yǔ)言中strcpy函數(shù)與memcpy函數(shù)的區(qū)別與實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C語(yǔ)言 strcpy memcpy內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲
這篇文章主要介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲,用到雙向隊(duì)列,方便在運(yùn)行完畢后輸出經(jīng)過的點(diǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04
C++可執(zhí)行文件絕對(duì)路徑值與VS安全檢查詳解
這篇文章主要給大家介紹了關(guān)于C++可執(zhí)行文件絕對(duì)路徑值與VS安全檢查的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-01-01
QT使用udp實(shí)現(xiàn)發(fā)送與接收?qǐng)D片
這篇文章主要為大家詳細(xì)介紹了QT如何使用udp協(xié)議實(shí)現(xiàn)發(fā)送與接收?qǐng)D片功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
C++中的static和const的關(guān)鍵字用法詳解
這篇文章主要介紹了C++中的static和const的關(guān)鍵字用法詳解,這是一道經(jīng)常在面試中被問到的知識(shí),本文給大家詳細(xì)介紹下,需要的朋友可以參考下2023-06-06

