这个章节,我们探讨C语言内存操作函数。
重点介绍处理内存操作函数使用和注意事项
和内存函数如何模拟实现。
内存函数所需头文件
#include<string.h>
memcpy
从source的位置开始向后复制num个字节的数据到destination的内存位置
void * memcpy ( void * destination, const void * source, size_t num );
参数说明:
destination: 指向用于存储复制内容的目标数组 。
source: 指向将要复制的数据。
num: 复制的字节个数
返回值:
返回一个指向 destination 首元素地址的指针
注意事项:
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
- 只要处理 不重叠的内存拷贝就可以
函数使用方法:
#include<stdio.h> #include<string.h> typedef struct Stu { char nane[20]; int age; }T; int main() { T t[3] = { {"张三",20},{"李四",30},{"小刘",40} }; T s[4] = { 0 }; memcpy(s, t, sizeof(t));//把t[3]的内容 拷贝到s里面 int i = 0; for (i = 0; i < 3; i++) { printf("%s %d\n", s[i].nane, s[i].age); } return 0; }
最终的输出结果:
张三 20
李四 30
小刘 40
memcpy 函数模拟实现
比较num个字节,把他转换成(char*)每次+1转换一个字节,直到转换num个字节。
#include<stdio.h> #include<string.h> void* my_memcpy(void* arr1, void* arr2, int num) { assert(arr1 && arr2); void* ret = arr1; while (num--) { *((char*)arr1) = *((char*)arr2); (char*)arr1 = (char*)arr1 + 1; (char*)arr2 = (char*)arr2 + 1; } return ret; }
memmove
memmove 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同
void * memmove ( void * destination, const void * source, size_t num );
参数说明:
- 指向用于存储复制内容的目标数组 。
- source: 指向将要复制的数据
- num: 复制的字节个数
返回值:
返回一个指向 destination 首元素地址的指针
注意事项:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
函数的使用方法:
#include<stdio.h> #include<string.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 }; int i = 0; memmove(arr + 2, arr, 20); for (i = 0; i < 9; i++) { printf("%d ", arr[i]); } return 0; }
最终的输出结果:
1 2 1 2 3 4 5 8 9
memmove 函数模拟实现
memmove函数的实现分两个部分,因为存在内存覆盖的情况,如果arr2首元素地址大于arr1首元素地址,那肯定需要从前往后拷贝,反之后往前即可。
void* my_memmove(void* arr1, void* arr2, int num) { assert(arr1 && arr2); char* ret = arr1; if (arr1 < arr2) { while (num--) { //从前往后 *((char*)arr1) = *((char*)arr2); (char*)arr1 = (char*)arr1 + 1; (char*)arr2 = (char*)arr2 + 1; } } else { //从后往前 while (num--) { *((char*)arr1 + num) = *((char*)arr2 + num); } } return ret; }
memcmp
内存存储的字节 str1 和 内存存储的字节 str2 的前 num 个字节进行比较
int memcmp(const void *str1, const void *str2, size_t num)
参数说明:
str1: 指向str1内存块的指针
str2: 指向str2内存块的指针
num: 要比较字节的个数
返回值:
- str1 大于 str2,则返回大于0的数字
- str1 等于str2 ,则返回0
- str1 小于 str2,则返回小于0的数字
函数的使用方法:
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4}; int arr2[] = { 1,2,3,5}; int ret = memcmp(arr1, arr2, 20); printf("%d\n", ret); return 0; }
memcmp 函数模拟实现
int mint my_memcmp(void* arr1, void* arr2, int num) { assert(arr1 && arr2); while (*((char*)arr1) == *((char*)arr2) && num--) { (char*)arr1 = (char*)arr1 + 1; (char*)arr2 = (char*)arr2 + 1; } if (*((char*)arr1) > *((char*)arr2)) { return 1; } else if (*((char*)arr1) < *((char*)arr2)) { return -1; } else { return 0; } }
memset
复制字符 c(一个无符号字符)到参数 str 所指向地址。复制num个字节
void *memset(void *str, int c, size_t num)
参数说明:
str: 指向要复制的的内存块地址
c: 是要被设置的值
num: 要复制多少个字节的个数
返回值:
返回指向srr首元素地址的指针
注意事项:
- 不能任意赋值,memset函数是按照字节对内存块进行初始化,如果是int类型的数组,只能初始化0或者-1.
- 注意memset,是按字节来复制的,而不是按元素个数,经常有人在这里出错。
函数的使用方法:
#include<stdio.h> #include<string.h> int main() { char arr[] = "abcdef"; memset(arr, '#', 4); printf("%s\n", arr); return 0; }
memset 函数模拟实现
void* my_memset(void* arr, int set, int num) { assert(arr); void* ret = arr; while (num--) { *((char*)arr) = (char)set; (char*)arr = (char*)arr + 1; } return ret; }