浅谈C库函数——memcpy、memmove、memcmp、memset函数
创始人
2025-05-30 20:02:15
0

 

💌内容专栏:【C语言】进阶部分

💌本文概括:理解C库函数memcpy、memmove、memcmp、memset内存函数

💌本文作者:花 碟

💌发布时间:2023.3.19

 

目录

 一、memcpy函数

1.函数声明

2.函数参数

3.函数返回值

4.用法 

5.模拟实现

二、memmove函数

1.函数声明

2.函数参数

3.函数返回值

4.用法

5.模拟实现

三、memcmp函数

1.函数声明

2.函数参数

3.函数返回值

4.用法

5.模拟实现

四、memset函数

1.函数声明

2.函数参数

3.函数返回值

4.使用


 一、memcpy函数

简要描述:内存拷贝,可以拷贝任何数据类型的对象。

1.函数声明

下面是 memcpy() 函数的声明

从存储区 source 复制 num 个字节的数据 拷贝到存储区 destnation。

void * memcpy ( void * destination, const void * source, size_t num );

2.函数参数

  • destnation -- 指向用于存储拷贝内容的目标数组,类型强制转换为 void* 指针。
  • source -- 指向要拷贝的数据源,类型强制转换为 void* 指针。
  • num -- 要被拷贝的数据字节数

3.函数返回值

返回目标存储区destnation的起始地址

4.用法 

#include
#include
void test1()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };//把arr1的前5个数据拷贝到arr2中memcpy(arr2, arr1, 20);printf("%d", arr2);
}
void test2()
{float arr3[] = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };float arr4[10] = { 0.0 };//把arr3的前3个数据拷贝到arr4中memcpy(arr4, arr3, 12);printf("%d", arr4);
}
int main()
{test1();test2();return 0;
}

5.模拟实现

void*的类型不能直接解引用和运算,所以我们考虑强制类型转换为char*的类型最合适。

#include
void* my_memcpy(void* dest, void* src, int num)
{void* ret = dest;assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}
void test3()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memcpy(arr2, arr1, 20);
}
int main()
{test3();return 0;
}

 那么问题来了,假设我们要把arr1中的1,2,3,4,5的数据拷贝到3,4,5,6,7的位置,即数组数据由1,2,3,4,5,6,7,8,9,10 变为 1,2,1,2,3,4,5,8,9,10 这样子的结果呢?

其实,我们会发现这样的结果打印的话(只需将上面的目标空间地址改为arr+2),得到的是1,2,1,2,1,2,1,8,9,10   这是因为,我们在开始拷贝的1,2时,已经把后面的3,4给覆盖掉了,往后拷贝就只能拿到1,2两个数字了。

所以,我们发现在内存重叠的时候,使用memcpy可能会出现意想不到的结果。

由此,我们需要知道memmove这个库函数了 。

二、memmove函数

简要描述:

在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。

1.函数声明

 从存储区 source 复制 num 个字节的数据 拷贝到存储区 destnation

void * memmove ( void * destination, const void * source, size_t num );

2.函数参数

  • destnation -- 指向用于存储拷贝内容的目标数组,类型强制转换为 void* 指针。
  • source -- 指向要拷贝的数据源,类型强制转换为 void* 指针。
  • num -- 要被拷贝的数据字节数。

3.函数返回值

返回目标存储区destnation的起始地址

4.用法

在内存重叠的前提下,将1,2,3,4,5 的数据拷贝到 3,4,5,6,7 的目标区域中

#include
#include
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//将1 2 3 4 5五个数据拷贝到 3 4 5 6 7的位置memmove(arr1 + 2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

5.模拟实现

思路:我们可以看到,之所以memcpy函数不能拷贝重叠区域的数据,是因为将源空间的数据从头开始拷贝导致的覆盖,所以针对这种情况,我们可以从后往前一一拷贝。

但是只有这一种情况吗?假设,我们调换刚才的源目两空间的位置,将3,4,5,6,7 拷贝到1,2,3,4,5 之中呢?我们就需要从前往后拷贝了。

所以我们要针对不同的情况使用不同的解决方案呢来解决。

 如图可以得出,当dest在②or③的位置(dest < src),我们选择从后往前拷贝,当

dest在①的位置(dest >= src ),我们选择从前往后拷贝。

代码实现:

#include
void* my_memmove(void* dest, void* src, int num)
{void* ret = dest;assert(dest && src);if (dest < src){//从前往后拷贝assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//从后向前拷贝while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;
}#include
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//将1 2 3 4 5五个数据拷贝到 3 4 5 6 7的位置my_memmove(arr1, arr1 + 2, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

三、memcmp函数

简要描述:与strcmp函数相比,memcmp函数功能则更强大,它能够与各种类型的数据进行比较。

1.函数声明

ptr1 指向的内存块的前 num 字节数与 ptr2 指向的内存块的前 num 字节数一一比较,如果它们都匹配,则返回零,如果不匹配,则返回一个不同于零的值,表示哪个值更大。它与strcmp不同,该函数在找到空字符后不会停止比较。

int memcmp ( const void * ptr1, const void * ptr2, size_t num )

2.函数参数

  • ptr1 -- 指向内存块的指针。
  • ptr2 -- 指向内存块的指针。
  • num -- 要被比较的字节数。

3.函数返回值

  • 如果返回值 < 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str1 大于 str2。
  • 如果返回值 = 0,则表示 str1 等于 str2。

4.用法

将arr1内存块的前28个字节与arr2内存块的前28个字节进行比较。

#include
#include
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[] = { 1,2,3,4,5,6,6,6,6,6 };int ret = memcmp(arr1, arr2, 28);printf("%d", ret);}

5.模拟实现

#include
#include
int my_memcmp(const void* e1, const void* e2, int num)
{int i = 0;for (i = 0; i < num; i++){if (*((char*)e1 + i) > *((char*)e2 + i) || *((char*)e1 + i) < *((char*)e2 + i))return *((char*)e1 + i) - *((char*)e2 + i);	 }return 0;
}
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };int ret = my_memcmp(arr1,arr2,24);printf("%d", ret);
}

四、memset函数

 简要描述:C 库函数 void *memset(void *str, int c, size_t n) 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符

1.函数声明

void *memset(void *str, int c, size_t num);

2.函数参数

  • str -- 指向要填充的内存块。
  • c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
  • num -- 要被设置为该值的字符数。

3.函数返回值

该值返回一个指向存储区 str 的指针。

4.使用

#include
#include
int main()
{char arr1[] = "hello world!";memset(arr1, 'x', 5);printf("%s", arr1);return 0;
}

错误使用:

以下的代码可能认为是将arr2数组的所有元素都初始化为1,但是是错误的,打印%d,数据是十个很大的数字,以%p打印,我们发现其实是每个元素的4个字节都初始化为1。

故而不能使用这样的方式将数组所有元素初始化为1。

//error
#include
int main()
{int arr2[10] = { 0 };//将数组的元素都初始化为1memset(arr2, 1, sizeof(arr2));int i;for (i = 0; i < 10; i++){//printf("%d ", arr2[i]);printf("%p ", arr2[i]);}return 0;
}

以%d打印:

以%p打印:


 好了,本篇文章就到这里,有什么问题,可以私信博主~~ 感谢大家的支持!

相关内容

热门资讯

王凤英入职小鹏3年终获股权,此... 5月7日消息,小鹏汽车披露的监管及年报信息显示,公司总裁王凤英已正式进入股东名册,入职小鹏3年后股权...
五块钱红酒卖断货,便宜红酒为何... 最近一段时间,中国的酒类消费市场可以说是显得格外奇怪,一方面,各种高端酒特别是白酒的消费量出现了明显...
财联社C50风向指数调查:4月... 财联社5月8日讯(记者 夏淑媛)新一期财联社“C50风向指数”结果显示,市场机构对4月新增人民币贷款...
央视硬刚国际足联拒掏20亿,背... 作者| 史大郎&猫哥 来源| 是史大郎&大猫财经Pro 央视这次太刚了,离世界杯开幕还有1个月,死活...
新CEO上任直接放大招!Air... 快科技5月8日消息,苹果即将上任的CEO John Ternus对未来一系列新产品充满信心,称这些设...
“特朗普拟邀英伟达、波音等CE... 据路透社当地时间5月7日报道,特朗普政府正邀请英伟达、苹果、埃克森美孚、波音等大公司首席执行官,于下...
世界杯,还能看到直播吗? 2026年美加墨世界杯距离开幕,仅剩一个多月时间。多方信息显示,中央广播电视总台(以下简称“央视”)...
机构警告AI芯片热潮风险,超威... 5月7日,据央视财经,隔夜超威半导体公司(AMD)股价飙升近19%,带动AI芯片热潮持续升温。AMD...
银行员工转走储户1800万最新... 银行员工转走储户1800万最新进展:2名储户已收到银行全部款项
原创 中... 1994年,安徽省的经济格局曾发生过一次戏剧性的转折。在那一年,一座名为安庆的城市,其国内生产总值(...
昆都仑区:政策“蓄力”消费焕新 “一台5000多元的空调,叠加‘国补’和商场的以旧换新活动,能优惠1000元左右,旧机还能免费上门拆...
乐悦置业竞得佛山顺德乐从镇一商... 观点网讯:5月6日,佛山市顺德区乐从镇一商业地块成功出让,由广东省乐悦置业有限公司竞得,乐从南区·邻...
原创 亦... 《爱情没有神话》这部剧,一开始的命运颇为多舛,经历了几次撤档的波折后,终于在观众面前亮相,但其首播的...
美联储34年最大分歧叠加油价飙... 美联储按预期维持利率不变,但内部出现34年来最严重分歧,叠加布油创2022年6月以来新高,美债遭抛售...
支付宝消费券回收后,资金是否支... 摘要: 支付宝消费券回收变现后,资金能否直接转入信用卡?本文解答到账方式的相关规则,帮助用户了解资金...
中医介绍5个化痰穴位!收藏这篇... 很多人忽略了“痰”的危害,觉得咳几下就没事,殊不知,肺里的痰长期堆积,只会一步步加重身体负担。 中医...
黄金平台“杰我睿”涉嫌经济犯罪... 红星资本局5月7日消息,深圳水贝知名金店“杰我睿”兑付困难事件有了新进展。日前,深圳市公安局罗湖分局...
多地出台购房新政促楼市升温 记... 今年的“五一”假期,伴随着多个城市楼市新政密集落地,在叠加市场信心持续修复的作用下,房地产市场热度持...
谁是五一“吸金王”?这5座城市... 来源:市场资讯 (来源:21城市观) 哪座城市成为“五一”假期的大赢家? 图源:摄图网 作者|赵晓...
“低招低裁”格局稳固劳动力市场... 智通财经APP获悉,美国上周初请失业金人数在经历前一周回落至近几十年来最低水平后出现小幅反弹,表明尽...