前言:
Hello各位小伙伴们,上期我们介绍了C语言的字符串函数的使用和模拟,这期我们来介绍一下C语言内存函数。
C语言的内存函数与字符串不同的是前者不在考虑类型,直接把这块的内存进行处理,不在有字符这一限制。所以处理的内容类型不同所以指针类型是void*类型。这里具体介绍一下memcpy,memmove,还有memset的使用和模拟实现。
memcpy的使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
与strncpy相比十分类似,只不过指针类型为void*,因为拷贝的内容无法确定类型,所以使用void*。返回类型仍为destination is returned.
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存置。
• 这个函数在遇到 '\0' 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。
同时要注意的是在memcpy,memmove,还有memset中的单位都是字节。memcpy在拷贝的过程中都是以字节为单位进行拷贝。
#include<stdio.h>
#include<string.h>
int main ()
{
int arr1[] = { 1,2,3,4 };
int arr2[5] = { 0 };
memcpy(arr2,arr1,3*sizeof(int))
for(int i = 0;i < 5;i++)
{
printf("%d ",arr2[i]);
}
}
要注意的是由于memcpy的单位是字节,所以在确定拷贝元素个数的时候,要以字节为单位。如果要拷贝3个整数,则需要在size_t 处写成12及3*sizeof((int))。
模拟实现:
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while(num--)
{
*(char*)dest = *(char*)src;//强置类型转化是临时的
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[6] = { 0 };
int arr2[] = { 1,2,3,4,5 };
my_memcpy(arr1, arr2, 4 * sizeof(int));
for (int i = 0; i < 6; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
因为单位是字节所以在强制类型转化的时候转化成char*类型,char*一次访问一个字节。
同时值得注意的是memcpy是在拷贝不会重合的情况下使用,但在拷贝重合时在VS上仍然适用但最好使用memmove。
memmove的使用和模拟实现
memmove是在出现重叠的情况下使用。
void * memmove ( void * destination, const void * source, size_t num );
#include<stdio.h>
#include<string.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
memmove(arr + 2, arr, 4 * sizeof(int));
for (int i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
return 0;
}//1 2 1 2 3 4 7 8 9
模拟实现:(在出现重叠的情况下)
现在我们分析一下该过程在上述代码中我们只考虑了一种情况就是dest在src的前面:
此时在进行拷贝的时候从src的第一位向dest的第一位进行拷贝,及从前向后拷贝
另一种情况是src在dest的前面:
此时在进行拷贝的时候从src的最后一位向dest的最后一位进行拷贝,及从后向前拷贝
代码展示:
#include<stdio.h>
void*my_memmove(void*dest, void*src, size_t num)
{
//从前向后拷贝
if(dest<src)
{
while(num--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
//从后向前拷贝
else
{
while(num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
my_memmove(arr + 2, arr, 4 * sizeof(int));
for (int i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
当dest和src不出现重叠情况的时候,上述模拟同样满足,小伙伴们可以自行尝试一下。
memset的使用和模拟实现
void * memset ( void * ptr, int value, size_t num );
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
一般情况下我们想要将一个数组元素进行修改的话,需要使用for循环进行一个数组的遍历。例如:
#include<stdio.h>
int main ()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 } //将数组元素修改为7
for(i = 0;i < 10;i++)
{
arr[i] = 7;
}
//打印数组
.........
return 0;
}
此时我们可以使用memset进行一个数组元素的修改
#include<stdio.h>
#include<string.h>
int main ()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
memset(arr,0,4*sizeof(int));
for(int i = 0;i < 10;i++)
{
printf("%d ",arr[i]);
}
}//0 0 0 0 5 6 7 8 9 10
同时值得注意的是int value,size_t num 单位都是字节。
同时memset还可以设置字符数组:
#include<stdio.h>
#include<string.h>
int main ()
{
char arr[] = "Good morning ";
memset(arr,'*',4);
printf("%s",arr);
}
此时就不在特殊考虑单位是字节的问题,因为sizeof(char)为1。
模拟实现:
#include<stdio.h>
#include<assert.h>
void*my_memset(void*dest,char str,size_t num)
{
assert(dest);
void *ret = dest;
while(num--)
{
*(char*)dest = str;
dest = (char*)dest + 1;
}
return ret;
}
int main ()
{
char arr[] = "Good morning";
my_memset(arr,'*',4);
printf("%s",arr);
}
memcmp的使用和模拟实现
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
• 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
• 返回值如下:
Return Value:
Returns an integral value indicating the relationship between the content of the memory blocks:
return value | indicates |
---|---|
<0 | the first byte that does not match in both memory blocks has a lower value in ptr1 than in ptr2 (if evaluated as unsigned char values) |
0 | the contents of both memory blocks are equal |
>0 | the first byte that does not match in both memory blocks has a greater value in ptr1 than in ptr2 (if evaluated as unsigned char values) |
和strcmp不同的是,memcmp比较的是内存块中字节的个数。
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8 };
int arr2[] = { 1,2,3,3 };
//1----在内存中的存储倒着存放:01 00 00 00
int ret = memcmp(arr1, arr2, 12);
printf("%d", ret);
return 0;
}
模拟实现就靠各位小伙伴自己动手尝试吧,我们下期再见。