内存函数的学习

额外知识点

第一个 

 假设c为int类型,(char)c之后,之后如果还用变量c的话,c依然为int类型。()强制转换操作符并不会永久改变原本的变量类型。

第二个

\0在打印时不会显示出来 

第三个 

 void *能接收任意类型指针,除了被const修饰的指针类型。 我们要接受被const修饰的指针,就要用const void* 去接受。 

memcpy和memmove

memcpy

其格式为

其作用是将从source往后的num个字节拷贝到destination上。(从前往后拷贝)

 memcpy相比于strcpy

strcpy只适用于字符串,并且遇到\0就自动结束拷贝

memcpy 对于任何数据类型都能拷贝,所以用void*接收,并且遇到\0不会结束,它只在拷贝完num的字节后结束。

 如果destination和source中有重叠的内存,那么就不能用memcpy,否则会发生错误。这时候我们要用到memmove。

有人在vs2022用memcpy对有重叠内存的参数进行拷贝,但是正常结果,这并不代表memcpy本身有能对重叠内存的参数进行拷贝的功能,而是vs2022使memcpy能实现该功能,在其他编译器就不一定了。

所以如果发生这种情况,我们就用memmove,不能用memcpy,即使它在编译器的帮助下也能实现。

 

 memcpy的模拟实现

void * memcpy ( void * dst, const void * src, size_t count)
{
 void * ret = dst;
 assert(dst);
 assert(src);
 /*
 * copy from lower addresses to higher addresses
 */
 while (count--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst + 1;
 src = (char *)src + 1;
 }
 return(ret);
}

在这我们还知道,对dst 强制类型转换为char*后,并没改变dst的本质void*类型,其本质依然为void*类型,之后如果要用还是要强制转换才能用。

 memmove

其格式和memcpy一模一样 

其实可以理解memmove为高配的memcpy,当其不重叠时,可以实现,当其重叠时依然可以实现。 而memcpy只能实现不重叠的,重叠的不能实现。 更加高级。 

 

当重叠时,如果依旧拷贝,并且结果依然为正确,那就必须遵循:

当source在dest左边时,向左复制(从后往前复制)。如果source在dest右边,向右移动(从前往后复制)。

所以模拟memmove的代码为

void * memmove ( void * dst, const void * src, size_t count)
{
 void * ret = dst;
 if (dst <= src || (char *)dst >= ((char *)src + count)) {
 /*
 * Non-Overlapping Buffers
 * copy from lower addresses to higher addresses
 */
 while (count--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst + 1;
 src = (char *)src + 1;
 }
 }
 else {
 /*
 * Overlapping Buffers
 * copy from higher addresses to lower addresses
 */
 dst = (char *)dst + count - 1;
 src = (char *)src + count - 1;
 while (count--) {
 *(char *)dst = *(char *)src;
 dst = (char *)dst - 1;
 src = (char *)src - 1;
 }
 }
 return(ret);
}

 memset 

 memset是从ptr地址开始,将每个字节的值变为value值,改变num个字节。

在使用时,由于其改变是改变一个字节,如果在对整形做改变,因为整形为四个字节,所以起不到很好的效果,一般我们都是对字符数组做改变。 (常量字符串不可修改,所以不能当作参数被修改,类型带const,不能被void*接收)

因为是改变一个字节,且一般对字符数组做改变。所以value使用时一般为字符 。

下图是使用时的一个经典例子,一般使用memset都是对字符数组进行改变,使其等于的值一般都为字符。 

#include <stdio.h>
#include <string.h>
int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

memcmp

 

 

跟strncmp有点像,只不过一个比字符(只能作用于字符串),一个比字节(任意数据都可以)。 其作用原理本质几乎差不多,就从第一个字节大小比较,如果相等比较下一个字节大小。第一个大于第二个返回大于0的整数,相反则返回小于0,相等则返回0.

下面举个例子 

#include <stdio.h>
#include <string.h>
int main()
{
 char buffer1[] = "DWgaOtP12df0";
 char buffer2[] = "DWGAOTP12DF0";
 int n;
 n = memcmp(buffer1, buffer2, sizeof(buffer1));
 if (n > 0) 
 printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
 else if (n < 0) 
 printf("'%s' is less than '%s'.\n", buffer1, buffer2);
 else
 printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
 return 0;
}

 

 总结

这就是我们的内存函数 ,其头文件都为#include<string.h>.到这里,我们就讲了四个内存函数,都是以字节为单位去作用。

之后我们将给大家介绍数据在内存中的存储,谢谢大家!

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值