您的位置:首页 > 房产 > 建筑 > 酒店网页设计素材_简单的购物网站设计_网络seo优化_网络营销推广实训报告

酒店网页设计素材_简单的购物网站设计_网络seo优化_网络营销推广实训报告

2025/1/10 0:11:49 来源:https://blog.csdn.net/ljh1257/article/details/144965465  浏览:    关键词:酒店网页设计素材_简单的购物网站设计_网络seo优化_网络营销推广实训报告
酒店网页设计素材_简单的购物网站设计_网络seo优化_网络营销推广实训报告

前言

本篇博客主要介绍常用的4个内存操作函数:
1.不重叠内存拷贝函数 – memcpy()
2.重叠内存拷贝函数 – memmove()
3.内存比较函数 – memcmp()
4.内存填充函数 – memset()

使用这4个函数均需要包含头文件string.h

文章目录

  • 前言
  • 1. 不重叠内存拷贝函数 -- `memcpy()`
    • 1.1 函数功能介绍
    • 1.2 参数及返回值介绍
    • 1.3 使用`memcpy`拷贝各类型数据
      • 1.3.1 代码
      • 1.3.2 输出结果
      • 1.3.3 解释
    • 1.4 使用细节
    • 1.5 `memcpy`函数的模拟实现
  • 2. 重叠内存拷贝函数 -- `memmove()`
    • 2.1 函数功能介绍
    • 2.2 `memmove()`的实现原理
      • 2.2.1 第一种重叠形式
      • 2.2.2 第二种重叠形式
      • 2.2.3 总结
    • 2.3 模拟实现`memmove()`
  • 3.内存比较函数 -- `memcmp()`
    • 3.1 函数功能介绍
    • 3.2 代码举例
      • 3.2.1 比较整型数据
      • 3.2.2 比较字符串(对比`strncmp`)
  • 4. 内存填充函数 -- `memset()`
    • 4.1 初始化`malloc`开辟的数组
    • 4.2 初始化结构体变量
    • 4.3 初始化结构体数组

1. 不重叠内存拷贝函数 – memcpy()

1.1 函数功能介绍

函数memcpysource指向的内存空间的前num个字节的数据复制到destination指向的空间中。
函数数功能图解

1.2 参数及返回值介绍

函数原型:

void* memcpy ( void * destination, const void * source, size_t num );
  • 参数1:destination – 指向用于存储复制内容的目标空间,类型强制转换为 void* 指针。

  • 参数2:source – 指向要复制的数据源,类型强制转换为 void* 指针,const关键字保证数据源不会被修改。

  • 参数3:num – 要被复制的字节数。

  • 返回值:目标空间地址destination,类型为void*

1.3 使用memcpy拷贝各类型数据

1.3.1 代码

(来自网站cplusplus)

#include <stdio.h>
#include <string.h>struct {char name[40];int age;
} person, person_copy;int main()
{char myname[] = "张三";/* 1. 使用 memcpy 拷贝 字符串 */memcpy(person.name, myname, strlen(myname) + 1);person.age = 46;/* 2. 使用 memcpy 拷贝 结构体数据: */memcpy(&person_copy, &person, sizeof(person));printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);/* 3. 使用 memcpy 拷贝 数组数据 */int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr_copy[10] = { 0 };memcpy(arr_copy, arr, sizeof(arr));printf("arr_copy: ");for (int i = 0; i < 10; i++)printf("%d ", arr_copy[i]);return 0;
}

1.3.2 输出结果

person_copy: 张三, 46
arr_copy: 1 2 3 4 5 6 7 8 9 10

1.3.3 解释

  1. memcpy(person.name, myname, strlen(myname) + 1);
    • 第一个参数person.name是指向待放数据数组首元素的指针变量。
    • 第二个参数myname是指向待拷贝的源头数组首元素的指针变量。
    • 第三个参数为表达式strlen(myname) + 1strlen(myname)表示字符串长度(单位:字节),+1表示将'\0'拷贝过去
  2. memcpy(&person_copy, &person, sizeof(person));
    • 第一个参数&person_copy是待放拷贝数据的结构体空间首地址。
    • 第二个参数&person是待拷贝的源头结构体空间首地址。
    • 第三个参数sizeof(person),表示将结构体person的全部内容拷贝到结构体person_copy(单位:字节)。
  3. memcpy(arr_copy, arr, sizeof(arr));
    • 第一个参数arr_copy是待放拷贝数据的数组首元素地址。
    • 第二个参数arr是待拷贝的源头数据数组首元素地址。
    • 第三个参数sizeof(arr)表示拷贝内容大小为40个字节

在这里插入图片描述

1.4 使用细节

  1. 这个函数在遇到 ‘\0’ 的时候并不会停下来。

在这里插入图片描述
2. 前面讲到过,memcpy是使用在不重叠的内存块之间的拷贝,但是,如果sourcedestination有任何的重叠,那么拷贝的结果又当如何——答案是不知道!
C语言官方文档中未对该状况做出明确定义,所以具体情况得看编译器提供的库函数是如何实现的。

假设使用memcpy进行重叠内存拷贝的预期结果:
在这里插入图片描述
实际运行的结果:
在这里插入图片描述
由于内存重叠,在拷贝过程中内存中的数据会受到改变,因此实际结果并非我们预期说想的结果。

  1. VS里面memcpy超额完成了功能,它能够进行重叠内存的拷贝。也就是使其拥有memmove的功能至于memmove又有什么功能,别急,下一个介绍的函数就是它。

1.5 memcpy函数的模拟实现

#include <assert.h>
void* myMemcpy(void* dest, const void* src, size_t num)
{assert(dest && src);for (size_t i = 0; i < num; i++)((char*)dest)[i] = ((char*)src)[i];return dest;
}

2. 重叠内存拷贝函数 – memmove()

2.1 函数功能介绍

void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

2.2 memmove()的实现原理

memmove很好地解决了memcpy在拷贝过程中源内存空间内容因被覆盖而被改变的问题

上面已经把为何会导致出现问题的原因讲的很详细了,所以这里的重点就放在memmove如何解决这个问题上来——在模拟实现memmove()的过程中进行解答

2.2.1 第一种重叠形式

在这里插入图片描述
从上面的拷贝原理图中看到,从src指向空间的数据被从低地址向高地址拷贝(从前向后拷贝)是行不通的。但是,拷贝的方式又不是只有这一种,为什么不试试从后向前拷贝呢?

图解如下:
在这里插入图片描述
拷贝过程中,即使内存中的数据本身被覆盖了,但是源数据本身该被拷贝的数据却并没有没改变。

2.2.2 第二种重叠形式

在这里插入图片描述
解决了上面第一种内存重叠情况的拷贝后,当出现遇到第二种内存重叠情况时,仔细分析一下不难发现这种情况下,更适合从前向后拷贝。

图解如下:
在这里插入图片描述

2.2.3 总结

在这里插入图片描述
以src为界,
dest < src时, 源空间数据从前向后拷贝。
dest >= src时,源空间数据从后向前靠拷贝。

2.3 模拟实现memmove()

include <assert.h>
void* myMemmove(void* dest, const void* src, size_t num)
{assert(dest && src);if (dest < src){for (size_t i = 0; i < num; i++)((char*)dest)[i] = ((char*)src)[i];}else{while(num--)((char*)dest)[num] = ((char*)src)[num];}return dest;
}

3.内存比较函数 – memcmp()

函数原型

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

3.1 函数功能介绍

字节为单位,比较内存空间ptr1ptr2的前num个字节的数据大小。

  • ptr1指向内存块1,类型为void*,可接受任何类型数据
  • ptr2指向内存块2,类型为void*,可接受任何类型数据
  • num表示待比较字节数
  • 返回值规则如下(图片来自cplusplus):在这里插入图片描述

3.2 代码举例

3.2.1 比较整型数据

在这里插入图片描述

第一次比较1个字节,arr2指向的第1个字节 > arr1指向的第1个字节,返回负数。
第二次预计比较21个字节,但是在第一个字节比较完毕时已返回比较结果

3.2.2 比较字符串(对比strncmp

在这里插入图片描述

从上面的代码例子可以看出,memcmpstrncmp二者之间的功能在大致上是相似的,但是,当字符> 串长度小于num时,strncmp遇到'\0'会结束,而memcmp不会,它继续比较,直到比较完num个字节

4. 内存填充函数 – memset()

void * memset ( void * ptr, int value, size_t num );

一言蔽之,函数将ptr指向的内存空间的前num个字节设定为默认值value,最后返回ptr
这个函数比较适合用来初始化一些书写不太方便的变量或者数组。

4.1 初始化malloc开辟的数组

两种初始化方式,使用memset比较方便

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main()
{int* arr1 = (int*)malloc(sizeof(int) * 10);int* arr2 = (int*)malloc(sizeof(int) * 10);//arr1初始化为全0memset(arr1, 0, sizeof(int) * 10);//arr2初始化为全0for (int i = 0; i < 10; i++)arr2[i] = 0;return 0;
}

4.2 初始化结构体变量

#include<stdio.h>
#include<string.h>struct student{int ID;char name[20];
};int main(){struct student stu;memset(&stu, 0, sizeof(stu));printf("%d\t%s", stu.ID, stu.name);return 0;
}

4.3 初始化结构体数组

#include<stdio.h>
#include<string.h>struct student{int ID;char name[20];
};int main(){struct student stus[10];memset(stus, 0, sizeof(stus));printf("%d\n", stus[0].ID);printf("%s", stus[0].name);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com