引言:我们在上篇将C语言中常用的字符串函数进行了完整的讲解,那么这篇我们就来讲解内存函数,同时,内存函数也是包含在string.h这个头文件中。
目录
1.memcpy函数
1.认识memcpy函数
我们可以看到,memcpy函数返回的类型为void *类型,同时所传的参数为一个可修改地址内容的void *类型的指针和一个不可修改地址内容的void *类型的指针以及一个无符号整形。
而为什么使用void *类型的指针,我们可以这样想:在内存存储中,我们可能存放的是char *类型,也有可能是int *类型等等,所以我们只能用viod *类型。
注意:
2.memcpy函数的使用。
int main()
{
char arr[] = "abcdef";
char num[10] = { 0 };
int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
int num2[10] = { 0 };
memcpy(num, arr, 5 * sizeof(char));
memcpy(num2, arr2, 5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%c ", num[i]);
}
printf("\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", num2[i]);
}
return 0;
}
从代码和运行结果能看出,memcpy函数实际就是将一段内存内存放的内容复制去另一段内存。同时所传进去的整形实际就是所要复制的字节数。
(strcpy函数与memcpy函数在复制字符串的区别)
上一篇我们讲了,strcpy的停止方式是读取到“\0”,而memcpy函数是只要将传进去的字节数读取完就会停止,不会管“\0”;
我们通过下面的代码来了解
int main()
{
char arr1[] = "he\0llo";
char arr2[10] = { 0 };
memcpy(arr2, arr1, 5);
for (int i = 0; i < 5; i++)
{
printf("%c ", arr2[i]);
}
return 0;
}
可以看到,l与e之前是一个大空格,实际上应该是“\0”
调试结果如下
3.memcpy函数的模拟实现。
void* my_memcpy(void* add, const void* ess, size_t a)
{
void * ret = add;
while (a--)
{
*((char*)add) = *((char*)ess);
add = (char*)add + 1;
ess = (char*)ess + 1;
}
return ret;
}
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 0 };
char num1[5] = "hello";
char num2[5] = { 0 };
my_memcpy(arr2, arr1, 5 * sizeof(int));
my_memcpy(num2, num1, 5 * sizeof(char));
for (int i = 0; i < 5; i++)
{
printf("%d %c\n", arr2[i], num2[i]);
}
return 0;
}
注意:
1.在my_memcpy函数中,之所以要强制类型换成char*类型,是因为char *类型每次跳过1个字节,而int *类型跳过4个字节。
2.add = (char*)add + 1;改代码部分人可能会写成(char *)add++;这样写不能算错,但是在部分编译器是没法使用的。
2.memove函数
1.认识memmove函数
与memcpy函数一样,memmove函数返回的类型为void *类型,同时所传的参数为一个可修改地址内容的void *类型的指针和一个不可修改地址内容的void *类型的指针以及一个无符号整形。
注意:
2.memmove函数的使用
在讲memcpy函数时各位应该注意到了这样一句话:如果source和destination有任何的重叠,复制的结果都是未定义的。简单来理解就是说传入memcpy函数的参数内存是不可重叠的,而memmove函数所能处理的恰好就是可重叠的。
而何为重叠》在介绍memcpy函数时,int arr[1]与int arr[2]两者的内存是没有任何关系的,所以不会重叠,而当给memcpy函数传参时传入(arr[1],arr[1]),此时,这两者的内存则是重叠的。
memmove函数使用:
int main()
{
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr2+2, arr2,5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d \n", arr2[i]);
}
return 0;
}
这段代码中,我们想要将1 2 3 4 5复制到3 4 5 6 7中,此时传入的参数内存是重叠的,所以用memmove函数来处理。
3.memmove函数的模拟实现
void* my_memmove(void* str, void* dear, size_t a)
{
void* ret = str;
if (dear < str)
{
//后->前
while (a--)
{
*((char*)str + a) = *((char*)dear + a);
}
}
else
{
//前->后
while (a--)
{
*(char*)str = *(char*)dear;
str = (char*)str+ 1;
dear= (char*)dear + 1;
}
}
return ret;
}
int main()
{
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr2+2, arr2,5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d \n", arr2[i]);
}
return 0;
}
3.memset函数
1.认识memset函数
可以看到,memset函数的返回类型依然是void *类型,参数是一个void *类型的指针,一个整形和一个无符号整形。
后面第二句英文的解读可以理解为:从ptr位置开始,向后数num个字节,每个字节的内容修改为value。
所以我们可以把memset函数理解为设置内存。
2.memset函数的使用。
int main()
{
char arr[10] = "hello you";
//注意memset是以字节为单位设置的。
memset(arr, 'x', 5);
printf("%s", arr);
return 0;
}
4.memcmp函数
1.认识memcmp函数
可以看到,memcmp函数的返回类型为int,参数为两个void *类型的指针和一个无符号整形。
当大于时,返回大于0的数;相等时,返回0;小于时,返回小于0的数。
2.memcmp函数的使用
int main()
{
int arr[10] = { 1,2,3,4,5,6,9,8,9,10 };
int arr2[10] = { 1,2,3,4,5,9,6 };
int r = memcmp(arr, arr2, 21);
int n = memcmp(arr, arr2, 25);
printf("%d %d", r,n);
return 0;
}
本篇内容到此就结束了,感谢阅读。