目录
前言:
本文章会详解C语言中有关内存操作函数(memcpy,memmove,memcmp,memset)的使用说明。
一,内存初始化函数(memset)
1.函数说明
库函数memset函数声明:void*memset(void *dest,int c,size_t count)
dest:一块空间的起始地址。
c:对这块空间中每个字节要初始化的数据
count:从dest起始地址开始,要设置多少个字节的空间
返回值:返回dest空间地址。
2.模拟实现
#include<stdio.h>
#include<string.h>
void *my_memset(void *dest, int c, size_t count)
{
for (int i = 0; i < count; i++)
{
*(((char*)dest) + i) = c;
}
return dest;
}
int main()
{
char str[] = "Hello world";
my_memset(str, 0, sizeof(str));
return 0;
}
3.代码运行下的内存空间图示
红色部分为为原始的str内存空间的值
运行经过my_memset(str, 0, sizeof(str));
这时内存空间内的值全部被初始化为了0.
二,内存拷贝函数(memcpy)
1.函数说明
库函数memcpy函数声明:void *memcpy(void*dest,const void* src,size_t count);
dest:目标空间
src:源数据空间
count:大小
功能:从src指向的空间中拷贝count字节的数据到dest空间中。
返回值:返回dest空间首地址
2.函数实现过程,以及跟strcpy的区别
int main()
{
char str[] = "Hello world\0 fdsf dfsa";
char buf[1024] = { 0 };
strcpy(buf, str);
memset(buf, 0, 1024);
memcpy(buf, str, sizeof(str));
return 0;
}
我们特意在str这个字符串中加入了'\0'。用来观察strcpy和mencp的区别
(1)开始时buf的内存空间全都是0
(2)经过strcpy拷贝赋值后的内存空间
因为str中有’\0‘,strcpy拷贝时,如果遇到’\0‘就会终止,所以等于只拷贝了Hello world。
(3)经过memcpy拷贝赋值后的内存空间
memcpy不会去管’\0‘,它会一直往后去拷贝,一直把需要的数据拷贝完。
3.模拟实现
void *my_memcpy(void *dest, const void *src, size_t count)
{
assert(dest != NULL&&src != NULL);
char*d = (char*)dest;
char*s = (char*)src;
while (count--)
{
*d++ = *s++;
}
return dest;
}
三,memmove
1.函数说明
库函数memmove函数声明:void * memmove ( void * destination, const void * source, size_t num );
memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
2.模拟实现
void *my_memmove(void *dest, const void *src, size_t count)
{
assert(dest != NULL&&src != NULL);
char*d = (char*)dest;
char*s = (char*)src;
if (s >= d || d >= s + count)
{
//不考虑内存重叠
while (count--)
{
*d++ = *s++;
}
}
else
{
//发生内存重叠,进行反向拷贝
d= d + (count - 1);
s = s + (count - 1);
while (count--)
{
*d-- = *s--;
}
}
return dest;
}
int main()
{
char str[20] = "abcdefgh";
my_memmove(str + 2, str, 4);
printf("%s\n", str);
}
3.my_memcpy和my_memmove的区别:
主要就是区别就在存在内存重叠时的处理。
(1)对于my_memcpy
int main()
{
char str[20] = "abcdefgh";
my_memcpy(str + 2, str, 4);
}
在进行这个操作时,原本我们想得到的输出是:ababcdgh. 但是结果如下:
原因:由于在进行拷贝时,出现了内存重叠,本来应该拷贝的c被已经拷贝过来的a值所覆盖,导致又让a被拷贝了一遍。
(2)对于my_memmove
int main()
{
char str[20] = "abcdefgh";
my_memmove(str + 2, str, 4);
}
my_memmove在实现时,考虑到了内存重叠的情况,加入了一个判断语句,当出现内存重叠时,使用反向的拷贝方法,避免了这一问题的出现。
四,比较函数memcmp
1.函数说明
库函数memcmp函数声明:int memcmp ( const void * ptr1,const void * ptr2,size_t num );
memcmp与strcmp
函数功能相似,只不过是可以对所有类型都进行一个字节一个字节的比较,逐字节比较内存的大小.
返回值情况:
‘< 0’ :"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 < “参数ptr2”;(VS编译器下返回值为 -1)
‘= 0’: "参数ptr1"与"参数ptr2"内存大小相等;(VS编译器下返回值为 0)
‘> 0’:"参数ptr1"与"参数ptr2"逐字节比较,"参数ptr1"数据 > “参数ptr2”。(VS编译器下返回值为 1)