内存操作函数
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存操作函数相关的知识,希望对你有一定的参考价值。
一.内存操作函数
内存操作函数适用于任何类型,但是它是以字节为单位的。
1.memset函数
- 表现形式
适用于任何类型可以从void *看出。
- 作用
将ptr从第一个开始的num个字节赋值为value。
#include<stdio.h>
#include<string.h>
int main(){
int arr[10] = { 0 };
memset(arr, 1, sizeof(arr));//按字节为单位走 数字中的每一位为
printf("%x\\n", arr[0]);//0000 0001 0000 0001 0000 0001 0000 0001
return 0;
}
输出:
上面代码可以证明mem内存函数是以字节为单位的。
2.memcpy函数
- 表现形式
参数为地址。
- 作用
将source按num个字节拷贝到destination中。
注意:这个函数遇到’\\0’并不会停下来,因为是内存操作。
但source与destination有重叠的,拷贝得不到想要的结果,函数不起效的,原因在模拟实现中说明。
#include<stdio.h>
#include<string.h>
struct stu{
char name[20];
int age;
};
int main(){
struct stu s1;
char a[] = "Jimer";
char *p = memcpy(s1.name, a, strlen(a) +1);//strlen加1是为了将'\\0'拷贝进去。
printf("%s\\n", s1.name);
printf("%s\\n", p);
return 0;
}
输出:
3.memmove函数
- 表现形式
与memcpy相同。 - 作用
也与memcpy相同,但是如果source与destination空间有重叠的地方,这个函数是起效的,可以得到想要的结果。
用法与memcpy相同。
二.memcpy和memmove的模拟实现
上面说到,memcpy内存重叠时时不起效的,而memmove时起效的入下代码。
#include<stdio.h>
#include<string.h>
int main(){
char buff[] = "abcdefrt";
memcpy(buff+1, buff, strlen(buff) + 1);
memmove(buff+1, buff, strlen(buff) + 1);
return 0;
}
输出:
memcpy使buff变成了“aaaaaaaa”。
memmove函数使得 buff变成了“aabcdefrt”。
但是由于编译器已经将这一情况修正,所以输出仍然会得到想要的结果。但是我们要知道这种情况。
为什么会出现这种情况呢:
当第一个替换第二个时,第二个变成了a,第二个替换第三个时,第三个变成了a,如此。memcpy输出为全a,但是memmove出现这种情况时是从后往前拷贝的,这样就不会出现这种情况了。
memcpy模拟实现
#include<stdio.h>
#include<assert.h>
void *Mymemcpy(void* des, void* src, size_t size){
assert(des);//判断des,src不为NULL。
assert(src);
char *_des = (char *)des;//按字节为单位强转成char *
char *_src = (char *)src;
while (size--){
*_des=*_src;
_des++, _src++;
}
return des;
}
int main(){
char a[] = "abcdefrt";
char b[] = "asdfgh";
Mymemcpy(a, a+1, strlen(a)+1);
Mymemcpy(b+1, b, strlen(b) + 1);//上述内存重叠情况
printf("%s\\n", a);
printf("%s\\n", b);
return 0;
}
输出:
memmove模拟实现
只是在将上述内存重叠的情况单拎出来,从后往前拷贝。
情况为source首地址比destination首地址大,destination首地址比source尾地址大。
#include<stdio.h>
#include<assert.h>
void *Mymemmove(void* des, void* src, size_t size){
assert(des);
assert(src);
char *_des = (char *)des;//不能放在里面,在外面声明变量
char *_src = (char *)src;
if (_src < _des&&_des < (_src + size)){//先判定是哪种情况
_des += size-1;//指向最后一个元素的起始地址,如果加num指向的是最后一个元素的最后地址。
_src += size-1;
while (size--){//从后往前拷贝
*_des = *_src;
_des--, _src--;
}
}
else{
while (size--){//从前往后拷贝
*_des = *_src;
_des++, _src++;
}
}
return des;
}
int main(){
char a[] = "abcdefrt";
char b[] = "asdfgh";
Mymemmove(a, a + 1, strlen(a) + 1);
Mymemmove(b + 1, b, strlen(b) + 1);
printf("%s\\n", a);
printf("%s\\n", b);
system("pause");
return 0;
}
输出:
以上是关于内存操作函数的主要内容,如果未能解决你的问题,请参考以下文章
如何使用模块化代码片段中的LeakCanary检测内存泄漏?
Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段