一、简单了解
C语言内存函数有以下几个重要的:
1.memcpy( 复制内存块功能 )
2.memmove(移动内存块函数)
3,memset(设置内存函数)
4.memcmp(比较两个内存块函数)
二、各个函数的深层次理解
1、memcpy函数
void * memcpy ( void * destination, const void * source, size_t num );
这是函数的基本参数
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 ‘\0’ 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
上述代码会打印1,2,3,4,5,0,0,0,0,0.
为什么会这样呢?
memcpy(arr2, arr1, 20);因为这里的20并不是20个数字,而是20个字节,我们定义的是int类型的数组,int是四个字节,20个字节也就是五个数字;对于之后的五个数字就会根据初始化打印‘0’;
而 对于重叠的内存,交给memmove来处理。
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);
}
首先用ret接受dst数组,再分别断言两个数组不能为空,
紧接着进入循环,先将两个数组强制转换成char*类型,分别解引用并判断相等;//目的是让两个数组一个字节一个字节的访问下去
再让两个数组++一步一步向后走,直到count=0退出循环
最后返回ret。
2、memmove函数
void * memmove ( void * destination, const void * source, size_t num );
• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
• 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
同样的,这里的20也是20个字节,五个数字。
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);
}
整理框架是一个if语句的判断,判断dst和src 的大小,强制转换位char*类型,逐个字节访问,当符合条件的时候和momcpy一样进行循环,当不符合的时候基本是相反的,逐个字节判断,最后返回输出;
3、memset函数
void * memset ( void * ptr, int value, size_t num );
memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "hello world";
memset (str,'x',6);
printf(str);
return 0;
}
输出:
xxxxxxworld
memset (str,‘x’,6);
将str数组中的前六个字符变成‘x’;
4、memcmp函数
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节
• 返回值如下:
因为DWgAOtp12Df0 大于 DWGAOTP12DF0,因为两个单词中的第一个不匹配字符分别是“g”和“G”,并且“g”(103)的计算结果大于“G”(71)。