1. 简介
除了字符函数和字符串函数,<string.h>中还有一类内存操作函数,如memset(),memcmp()等函数,他们在功能和某些字符串函数很像,但作用范围更广,除了作用于字符串外,还可以作用于int ,double等内置类型,但因为是以字节为单位改变,所以限制也很大。下面就让我们来看看吧。
1.memcpy()函数
1.1memcpy()函数用法
- 声明:void *memcpy(void str1, const void str2, size_t n)
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void 指针。
str2 – 指向要复制的数据源,类型强制转换为 void 指针。
n – 要被复制的字节数。
2.作用:从存储区 str2 复制 n 个字节到存储区 str1。
3.返回值:该函数返回一个指向目标存储区 str1 的指针。
4.注意点:你如果source和destination有任何的重叠,复制的结果都是未定义的。所以memcpy()无法对自己进行拷贝。
1 .2 memcpy()函数用法实例
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
1.3模拟实现实现memcpy()
代码如下:
//模拟实现memcpy函数
void*my_memcpy(void* dest, const void* src, size_t n)
{
assert(dest && src);
void* ret = dest;
for (int i = 0; i < n; i++)
{
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
我们上面说过memcpy()无法对自己进行拷贝,那有没有能对自己拷贝的函数呢,当然有啦,就是我们的memmove()函数
2. memmove()函数
2.1 memmove()函数用法
1.声明:void *memmove(void str1, const void str2, size_t n)
str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void 指针。
str2 – 指向要复制的数据源,类型强制转换为 void 指针。
n – 要被复制的字节数。
2.作用:从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
2.2 memmove()函数用法实例
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "Hello, World!";
printf("原字符串: %s\n", str);
// 将字符串前6个字符移动到字符串的末尾
memmove(str, str + 7, 6);
printf("之后字符串: %s\n", str);
return 0;
}
输出结果:
原字符串: Hello, World!
之后字符串: World! World!
2.3模拟实现实现memmove()
这里主要有两个思路:思路一是先创建一个一样的新数组,把老数组数据复制到新数组中然后用老数组中的数据拷贝到新数组中,再把拷贝过后的新数组拷贝到老数组。这样一个思路比较麻烦而且浪费了空间。我们再看思路二:
//假设我们要拷贝的情况如下
int arr1[9] = { 1,2,3,4,5,6,7,8,9 };
my_memmove(arr1+4, arr1 + 2, 12);
思路二情况一
这种情况下
假设我们从3的位置开始拷贝,3-5,4-6,5-7,因为拷贝5—7时数据5已经变为数据3,所以目标拷贝失败。
如果我们从5的位置开始拷贝,:5-7,4-6,3-5,拷贝成功
思路二情况二
//假设需要拷贝以下场景
int arr1[9] = { 1,2,3,4,5,6,7,8,9 };
my_memmove(arr1, arr1 + 2, 12);
这种情况下
假设我们从3的位置开始拷贝,3-1,4-2,5-3,拷贝成功。
假设我们从5的位置开始拷贝,5-3,4-2,5-1,拷贝失败。
思路二情况三
两段没有重叠的情况,无论从开头拷贝还是从结尾拷贝都可以
int arr1[9] = { 1,2,3,4,5,6,7,8,9 };
my_memmove(arr1+1, arr1 + 5, 12);
my_memmove(arr1 + 5, arr1 + 1, 12);
总结:如果dest字符串在src的字符左边,则从首元素拷贝。如果dest字符串在src右边,则从末尾元素开始拷贝。
代码实现如下
void* my_memmove(void* dest, const void* src, size_t n)
{
assert(dest && src);//防止空指针
void* ret = dest;
if (dest <= src)//dest在src左侧
{
while (n--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//dest在src的右侧
{
dest = (char*)dest + n - 1;//指向末尾
src = (char*)src + n - 1;//指向末尾
while (n--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest - 1;
src = (char*)src - 1;
}
}
return ret;
}
3.memset()函数
2.1 memset()函数用法
1.声明:void *memset(void *str, int c, size_t n)
str – 指向要填充的内存块。
c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
n – 要被设置为该值的字符数。
2.作用:复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字节。
3.返回值:该值返回一个指向存储区 str 的指针。
4.memset()函数常用于初始化
2.2 memset()函数用法实例
c
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "hello world";
memset(str, 'x', 6);//以字节为单位
printf(str);
return 0;
}
输出结果:xxxxxxworld
示例二
int main()
{
int arr[4] = { 1,2,3,4 };
memset(arr, 1, sizeof(arr));
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出结果:16843009 16843009 16843009 16843009
虽然memset可以作用于int,float等类型,但是memset设置是以字节为单位,容易造成不符合我们预期的情况。
我们也可以通过查看内存来验证一下
4 . memcmp()函数
4.1memcmp()函数 用法
- 声明:int memcmp(const void *str1, const void *str2, size_t n)
str1 – 指向内存块的指针。
str2 – 指向内存块的指针。
n – 要被比较的字节数。
2.作用:把存储区 str1 和存储区 str2 的前 n 个字节进行比较。
3.返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
4.2memcmp()函数用法实例
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Hello, World!";
char str2[] = "Hello, World!";
char str3[] = "Hello, Betty!";
// 比较相同的字符串
if (memcmp(str1, str2, strlen(str1)) == 0)
{
printf("str1 和 str2 相同。\n");
}
// 比较不同的字符串
if (memcmp(str1, str3, strlen(str1)) != 0)
{
printf("str1 和 str3 不同。\n");
}
return 0;
}
输出:
str1 和 str2 相同。
str1 和 str3 不同。
🎈🎈完结撒花🎈🎈
🎈🎈完结撒花🎈🎈