目录

一、memcpy与memmove

memcpy与memmove的异同

memcpy

定义:

作用:

注意:

memmove

定义:

头文件:这里的memmove和memcpy的头文件都是string.h

代码实现

memcpy

memmove

二、memset

定义:

作用:

代码实现:

注意:

三、memcmp

定义:

作用:

实现

一、memcpy与memmove

memcpy与memmove的异同

首先我们来分别介绍一下memcpy和memmove

memcpy

定义:

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

这里我们可以看到memcpy有三个参数,第一个参数是终指针,第二个参数是源指针,第三个参数是需要拷贝的字节大小。

作用:

这个函数的作用是,将源指针开始的num个字节的空间大小拷贝到终指针开始的num个空间中。

但是我们看C语言标准中还有一句话,

注意:

To avoid overflows, the size of the arrays pointed to by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).

提醒了两个点,一、考虑num,防止溢出,二、内存不建议重叠,说如果重叠的话,使用memmove是更加安全。

memmove

定义:

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

其用法基本上与memcpy差不多,只是多了一句,强调可以用于内存重叠的情况。

所以综上可以知道了memmove与memcpy的区别了,他们基本用法一致,参数一致,只是memmove相当于对memcpy中未考虑内存重叠的情况的一个补充。

头文件:这里的memmove和memcpy的头文件都是string.h

代码实现

memcpy

#include

#include

void my_memcpy(void *arr2,void*arr1,int size)//这里由于不知道传进来的是什么类型,一律用void*

接收

{

char* p1 = (char*)arr1;//然后强转换成指向一个字节的char*类型,目的是一个一个字节地拷贝

char* p2 = (char*)arr2;

for (int i = 0; i < size; i++)//使用循环遍历数组拷贝

{

p2[i] = p1[i];

}

}

int main()

{

int arr1[10],arr2[10],arr3[10];

for (int i = 0; i < 10; i++)

{

arr1[i] = i;

}

memcpy(arr2,arr1,sizeof(arr1));//通过与库函数对比结果

my_memcpy(arr3,arr1,sizeof(arr1));

for (int i = 0; i < 10; i++)

{

printf("%d ",arr2[i]);

}

printf("\n");

for (int i = 0; i < 10; i++)

{

printf("%d ", arr3[i]);

}

return 0;

}

你会发现,这里我自定义的时候并没有遇到内存重叠的情况,如果碰到了内存重叠会出现什么样的情况呢?

#include

#include

void my_memcpy(void *arr2,void*arr1,int size)

{

char* p1 = arr1;

char* p2 = arr2;

for (int i = 0; i < size; i++)

{

p2[i] = p1[i];

}

}

int main()

{

int arr1[10],arr2[10],arr3[10];

for (int i = 0; i < 10; i++)

{

arr1[i] = i;

}

/*memcpy(arr2,arr1,sizeof(arr1));*/

my_memcpy(arr1+3,arr1,5);

for (int i = 0; i < 10; i++)

{

printf("%d ",arr1[i]);

}

return 0;

}

这里我传入的地址为arr1+3与arr1,得到的结果是什么呢?目的是想要将arr1数组的前五个值赋值到arr1第四个元素开始的五个值,预期结果为:0 1 2 0 1 2 3 4 8 9.   但是结果为:

并不是我们想要的结果,为什么呢?我们来看一下原因。

这里就是memcpy开始设计的时候没有考虑进去的情况,所以c标准里面才会标明,当内存重叠的时候,最好使用1memmove,但是当今的编译器里面很多已经考虑到了memcpy的这个缺陷,顾已经改正所以当使用memcpy的结果为:

是我们想要的结果。

memmove

如何实现memmove呢?这里就必需要考虑到内存重叠的问题了。

当内存重叠的时候,应该还要分两种情况。请看下图:

综上两种内存重叠的情况,由于内存不重叠的话,无论是从前往后还是从后往前,都是可以的,顾可以将所有的情况分为两种,从前往后和从后往前,这里怎么去区分这两种情况呢?

可以看地址高低!!如果源地址在前面即源地址大小小于目标地址,这里的话就可以用从后往前,反之则从前往后。好分析完毕之后让我们来代码实现一下吧!

代码如下:

#include

#include

void my_memmove(void *arr2,void*arr1,int size)

{

char* p1 = arr1;

char* p2 = arr2;

if (arr1 < arr2)//当源在前则从后头拷贝

{

for (int i = size - 1; i >= 0; i--)

{

p2[i] = p1[i];

}

}

else//源在后则从前头拷贝

{

for (int i = 0; i < size; i++)

{

p2[i] = p1[i];

}

}

}

int main()

{

int arr1[10],arr2[10],arr3[10];

for (int i = 0; i < 10; i++)

{

arr1[i] = i;

}

my_memmove(arr1+3,arr1,sizeof(arr1));

for (int i = 0; i < 10; i++)

{

printf("%d ",arr1[i]);

}

return 0;

}

二、memset

定义:

void * memset ( void * ptr, int value, size_t num );

这里有三个参数,第一个参数是一个指针,第二个参数是一个特定的值,第三个参数是一个大小。

作用:

Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).

即把ptr指向的内存前num个字节变成特定的一个值(这个值为无符号的char)

结合以上就很容易知道这个函数怎么用了。

代码实现:

#include

#include

void my_memset(void *ptr, int value, size_t num)

{

char *arr = (char*)ptr;

for (int i = 0; i < num; i++)

{

arr[i] = value;

}

}

int main()

{

char arr[] = "abacsdf";

my_memset(arr,'b',4);

puts(arr);

memset(arr,'a',4);

puts(arr);

return 0;

}

注意:

看一下下面的一段代码:

#include

#include

void my_memset(void *ptr, int value, size_t num)

{

char *arr = (char*)ptr;

for (int i = 0; i < num; i++)

{

arr[i] = value;

}

}

int main()

{

char arr[] = "abacsdf";

int arr1[10] = {0};

/*my_memset(arr,'b',4);

puts(arr);*/

memset(arr1,1,sizeof(arr1));

for (int i = 0; i < 10; i++)

{

printf("%d ",arr1[i]);

}

return 0;

}

这里我使用库函数memset来对int 类型的数组进行set发现得到一个比较奇怪的数字。

我们来分析一下原因:我们在创建这个函数的时候,是用void*来接收指针的,然后我们又将其转换成char*类型的指针进行逐一赋值。注意这里的char*每次只指向一个字节,而int 类型的数据在32位机器上是有4个字节的,这里我们就可以知道为什么了,这里每个字节都赋值成1,然后变成int类型看就会发现,正是上面出现的值00000001000000010000000100000001

所以在使用的时候要牢记一个点,memset这里的set是一个一个字节的赋值所以,不要用错了。

三、memcmp

定义:

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

这里同样有三个参数,两个参数是指针,最后是大小。

作用:

这里可以和strcmp进行比较,strcmp是比较整个字符串,而memcmp则是比较前num个字符。

注意定义强调了:Notice that, unlike strcmp, the function does not stop comparing after finding a null character.

这个函数并不会因为遇到NULL就停下来。

实现

#include

int my_memcmp(const void* p1, const void* p2, size_t num)

{

char* arr1 = (char*)p1;

char* arr2 = (char*)p2;

for (int i = 0; i < num; i++)

{

if (arr1[i] > arr2[i])

return arr1[i] - arr2[i];

if (arr1[i] < arr2[i])

return arr1[i] - arr2[i];

}

return 0;

}

int main()

{

char arr1[] = "acbafg";

char arr2[] = "acbagf";

if (my_memcmp(arr1, arr2, 4) == 0)

{

printf("arr1与arr2的前四个字符相同\n");

}

else

{

printf("arr1与arr2的前四个字符不相同\n");

}

if (my_memcmp(arr1, arr2, 5) == 0)

{

printf("arr1与arr2的前五个字符相同\n");

}

else

{

printf("arr1与arr2的前五个字符不相同\n");

}

return 0;

}

结果如下:

以上就是介绍的四个和内存相关的函数。

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: