内存函数可在任意类型使用,字符串函数只能比较字符串,内存函数不关注’\0’, 只关注要拷贝的字节数
一、memcpy
void * memcpy ( void * destination, const void * source, size_t num )
✔功能演示:参数类型必须是void*。因为memcpy函数是内存拷贝函数,它必须什么类型都能接收。
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置,这个函数在遇到 '\0' 的时候并不会停下来。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
int arr1[] = {1,2,3,4,5,6,7,8,9 };
int arr2[10] = {0};
memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++) {
printf("%d", arr2[i]);
}
return 0;
}
模拟实现memcpy
✔void 类型不能进行解引用操作和++运算,在解引用操作和++运算之前,要进行强制类型转换。并且因为此函数是一个字节一个字节的拷贝,所以要将ptr1和ptr2变量强制类型转化为char类型
✔目标变量dest的地址需要存放在一个临时指针变量中,因为dest在循环体中一直是变化的
✔将dest和sour指针变量assert断言,使其不为NULL。并且因为sour是不能改变的,所以用const修饰,以保护起来。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* sour, size_t num){
assert(dest && sour);
void* ret = dest;
while(num--){
*(char*)dest = *(char*)sour;
dest = (char*)dest + 1;
sour = (char*)sour + 1;
}
return ret;
}
int main() {
int arr1[] = {1,2,3,4,5,6,7,8,9 };
int arr2[10] = {0};
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 10; i++) {
printf("%d", arr2[i]);
}
return 0;
}
memcpy不支持自身内部拷贝,可能存在覆盖,主要负责拷贝两块独立空间中的数据,重叠内存拷贝使用memmove
二、memmove
void * memmove ( void * destination, const void * source, size_t num )
✔功能实现:如果源空间和目标空间出现重叠,就得使用memmove函数处理
#include<stdio.h>
int main() {
int arr1[] = { 1,2,3,4,5,6,7,8,9,10};
int arr2[10] = {0};
memmove(arr1, arr1+3, 20);
for (int i = 0; i < 10; i++) {
printf("%d", arr1[i]);
}
return 0;
}
模拟实现memmove
#include<
int main() {
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[] = {2,3,4,5,6,7,8,9,10};
my_memmove(arr1, arr1+2, 20);
my_memmove(arr2+2, arr2, 8);
for (int i = 0; i < 10; i++) {
printf("%d", arr1[i]);
}
printf("\n");
for (int i = 0; i < 9; i++) {
printf("%d", arr2[i]);
}
return 0;
}
为避免出现空间重叠现象,根据dest 和 sour 的位置分情况处理,选择从前向后或从后向前拷贝
#include<assert.h>
#include<stdio.h>
void* my_memmove(void* dest, const void* sour, size_t num) {
assert(dest && sour);
void* ret = dest;
if (dest < sour)
{
//前向后拷贝
while (num--)
{
*(char*)dest = *(char*)sour;
dest = (char*)dest + 1;
sour = (char*)sour + 1;
}
}
else
{
//后向前拷贝
while (num--)
{
*((char*)dest + num) = *((char*)sour + num);
}
}
return ret;
}
三、memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
✔功能实现:比较两个内存块,将 ptr1 所指向的内存块的前 num 个字节与 ptr2 指向的前num字节数进行比较, 返回不同意义的值
返回值 | 表明 |
---|---|
>0 | 在两个内存块中不匹配的第一个字节在 ptr1 中的值大于在 ptr2 中的值 |
0 | 两个内存块的内容相等 |
<0 | 在两个内存块中不匹配的第一个字节在 ptr1 中的值小于在 ptr2 中的值 |
#include<stdio.h>
#include<string.h>
int main(){
int arr1[] = { 1,5,4,5 };//01 00 00 00/ 05 00 00 00/ 04 00 00 00 /05 00 00 00
int arr2[] = { 1,3,5,6 };//01 00 00 00/ 03 00 00 00 /05 00 00 00/ 06 00 00 00
int ret = memcmp(arr1, arr2, 12);//arr1 > arr2
printf("%d", ret);
return 0;
}
模拟实现 memcpy()
✔void 类型不能进行解引用操作和++运算,在解引用操作和++运算之前,要进行强制类型转换。并且因为此函数是一个字节一个字节的拷贝,所以要将ptr1和ptr2变量强制类型转化为char类型
#include<stdio.h>
#include<assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
assert(ptr1 && ptr2);
while (num-- && *(char*)ptr1 == *(char*)ptr2){
ptr1 = (char*)ptr1 +1;
ptr2 = (char*)ptr2 +1;
}
return(*(char*)ptr1 - *(char*)ptr2);
}
int main(){
//char arr1[] = "hello world";
//char arr2[] = "hello bilibili";
int arr1[] = { 1,5,7,5 };
int arr2[] = { 1,5,7,6};
int ret = my_memcmp(arr1, arr2, 12);
if (ret == 0)
printf("==\n");
else if (ret < 0)
printf("<\n");
else
printf(">\n");
return 0;
}
四、memset()
void * memset ( void * ptr, int value, size_t num );
✔功能实现:将 ptr 所指向的内存块的前num个字节数设置为指定值
#include<stdio.h>
int main() {
char arr[] = "hello bilibili";
memset(arr, 'x', 5);
printf("%s", arr);
return 0;
}
模拟实现memset()
void* my_memset(void* ptr, int value, size_t num) {
assert(ptr);
void* ret = ptr;
while (num--){
*(char*)ptr = value; //赋值
ptr = (char*)ptr + 1; //q
}
return ret;
}