C语言内存函数的具体使用
作者:爱编程的小新☆
前言
上期我们学习了字符函数以及字符串函数,但是字符串函数仅仅只能对字符进行操作,那么这次我们来学习一下内存函数
在C语言中内存函数是一组用于内存操作的标准库函数,它们定义在 <string.h>头文件中,这些函数用于复制、设置、比较内存区域等,接下来我们来学习一下C语言中常用的内存函数。
1. memcpy 使⽤和模拟实现
memcpy与strcpy非常相似,但是strcpy只能对字符进行复制操作,而memcpy可以对任意类型的数据进行复制操作。
1.1 memcpy的使用
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
- 这个函数在遇到 '\0' 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
memcpy的使用:
#include<stdio.h> #include<string.h> 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; }
运行结果:
可以这里的num参数为20, 表示从 arr1 复制20个字节的数据到 arr2中,因为这里复制的内容为整数,整形的大小占4个字节,所以arr2从arr1中复制了前5个数字(也就是20个字节的数据)
1.2 memcpy模拟实现
既然知道了memcpy函数是如何使用的,那么我们接下来探索一下memcpy是如何实现的
#include<stdio.h> #include<string.h> #include<assert.h> void* my_memcpy(void* dst, const void* src, size_t num) { void* ret = dst; assert(dst); assert(src); while (num--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } 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); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0; }
运行结果:
我们可以看见模拟实现的my_memcpy函数与上面使用的memcpy函数的运行结果是一样的
从中memcpy的前两个形参使用的是void *类型来接收的,void *类型不能进行解引用和加减运算,所以在解引用和加减运算之前需要强制转换成char *类型进行操作
函数的返回值是void*类型,返回的是目标地址,所以在进行指针运算前,我们需要先创建一个指针(ret)存储目标地址,当复制操作完成后,返回目标地址
注意这里的dst和src是指针变量,所以在使用前用assert断言判断一下是否为NULL(空指针),并且因为src指针指向的数据是不能被修改的,所以这里用const进行修饰。
注意:memcpy只负责处理内存不重叠的情况,对于重叠内存拷贝使用memmove
2. memmove 使⽤和模拟实现
memmove函数的参数与memcpy函数是一样的
- 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
- 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。
2.1 memmove的使用
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; memmove(arr1 + 2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
运行结果:
那么为什么memmove函数能够处理内存重叠的情况呢?接下来我们来模拟实现一下memmove函数。
2.2 memmove模拟实现
#include<stdio.h> #include<string.h> #include<assert.h> void* my_memmove(void* dst, const void* src, size_t count) { void* ret = dst; if (dst <= src || (char*)dst >= ((char*)src + count)) { while (count--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } } else { dst = (char*)dst + count - 1; src = (char*)src + count - 1; while (count--) { *(char*)dst = *(char*)src; dst = (char*)dst - 1; src = (char*)src - 1; } } return(ret); } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1 + 2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
memmove的模拟实现与memcpy是相似的,但是这里需要分为两种情况讨论:
1. 目标地址>源内存地址
如果目标地址 > 源内存地址,那么我们就需要将数据从后向前进行拷贝,如果从前向后进行拷贝就会发生下面的现象
当我们从后面向前拷贝就不会出现这种现象:
2. 目标地址<源内存地址
如果目标地址 < 源内存地址,那么我们就需要将数据从前向后进行拷贝
3. 目标地址=源内存地址
当目标地址=源内存地址时,既可以使用从前向后的方式拷贝也可以使用从后向前的方式拷贝。
3. memset 函数的使⽤
memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。
- ptr表示更改的起始地址
- value表示更改的内容
- num表示更改的字节数
memset的使用:
int main() { char str[] = "hello world"; memset(str, 'x', 6); printf(str); return 0; }
运行结果:
memset函数将str数组中的前6个字节的数据更改成了 ’x‘
4.memcmp 函数的使用
memcmp是用于比较两块内存
将指针 1 所指内存块的前 num 个字节与指针 2 所指内存块的前num个字节进行比较,如果它们完全匹配,则返回零,否则返回一个不等于零的值,表示哪个更大。
返回值如下:
memcmp函数的使用:
这里我们比较的是两个整形数组前4个数据的大小, 一个整形的大小为4个字节,所以比较的是16个字节数据的大小,arr前16个字节的数据<arr2前16个字节的数据,所以返回值为-1。
结语
那么以上就是C语言中常用的内存函数,学完内存函数后,对于复制、设置、比较等操作就不仅仅只局限在字符中了,也可以对任意类型的数据进行复制、设置、比较等操作。到此这篇关于C语言内存函数的具体使用的文章就介绍到这了,更多相关C语言内存函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!