C 学习笔记 —— 内存操作函数

news2024/10/7 20:31:16

文章目录

    • 内存操作函数
      • memcpy
        • 实例
      • memmove
        • 内存重叠问题
      • memcmp
        • 实例
      • memset
        • 不能任意赋值
    • 参考资料

内存操作函数

内存操作函数也是在<string.h>头文件中的

四个内存函数:
memcpy(内存拷贝)
memmove(内存移动)
memcmp(内存比较)
memset(内存设置)

memcpy

void * memcpy ( void * dst, const void * src, size_t num );

函数功能:函数memcpy从src的位置开始向后复制num个字节的数据到dst的内存位置。num是字节数。

这个函数在遇到 ‘\0’ 的时候并不会停下来。不管是什么数据类型,它都能来;strcpy只能针对字符串
要保证dst有足够的容量能容纳src。

如果src和dst有任何的重叠,复制的结果都是未定义的。
在这里插入图片描述

实例

#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, 5 * sizeof(int));//拷贝5个整型进去
    for (int i = 0; i < 5; i++)
    {
        printf("arr2[%d]=%d ,", i, arr2[i]);
    }
    printf("\n");
    
 
	float str1[] = { 1.0f,2.0f,3.0f,4.0f };//如果不写f编译器会把他当成double类型的数据
	float str2[5] = { 0.0 };
	memcpy(str2, str1, 8 * sizeof(float));
    for (int i = 0; i < 8; i++)
    {
        printf("str2[%d]=%f ,", i, str2[i]);
    }
	return 0;
}

memmove

void * memmove ( void* dst, const void* src, size_t num );

函数功能:memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

如果源空间和目标空间出现重叠,就得使用memmove函数处理。

num是字节个数。

memmove的复制过程就好像是将src中的字节首先被复制到一个不重叠的临时数组中,然后将字节从临时数组复制到dest。

内存重叠问题

#include <stdio.h>
#include <string.h>
 
int main(){
	int d[10]={1,2,3,4,5,6,7,8,9,10};
	memcpy(d+3, d, 7*sizeof(int));// 注意第三函数为字节数
	for(int i=0;i<10;i++){
		printf("%d ", d[i]);
	}
	return 0;
}
/*输出
1 2 3 1 2 3 4 5 6 7
*/

这里的结果虽然是预期的,可能是在最新版本中解决了,但是这个是不可靠的,也就是这里可能存在问题,结果不符合预期,因为memcpy不保证内存重叠部分的正确性。所以这里应该使用memmove

memcmp

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

比较从ptr1和ptr2指针开始的num个字节,注意这里的比较是每个byte逐一比较

返回的结果=0,表示ptr1和ptr2的相等,
返回结果为>0,表示ptr1比ptr2的大,
返回结果为<0,表示ptr1比ptr2的小。

num是比较的字节的个数

void*又暗示着参数可以是任意类型
strncmp只能比较字符串的大小;而memcmp可以比较任意类型

实例

#include <stdio.h>
#include <string.h>

int main()

{
    int arr1[] = { 1,2,3,4,5 };
    int arr2[] = { 1,2,5,4,3 };
    //在内存中的存储,小端存储模式,十六进制表示,两个数一组表示一个byte
    //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
    //01 00 00 00 02 00 00 00 05 00 00 00 04 00 00 00 03 00 00 00

    //int ret = memcmp(arr1, arr2, 8);//num = 8,表示8个字节的大小。这里比较数组中前两个数字。 =0
    int ret = memcmp(arr1, arr2, 9);//num = 9,表示9个字节的大小。 = -2

    printf("ret = %d\n", ret); //-2
    return 0;
}

返回值-2表示pt1<pt2

memset

void *memset( void *dst, int c, size_t num );

将缓冲区设置为指定的字符,num是字节的个数,一个字节一个字节的改。
返回类型是一个指向存储区dst的指针
memset是一个初始化函数,作用是将某一块内存中的全部设置为指定的值。

其实c的实际范围应该在0~255,因为memset函数只能取c的后八位给所输入范围的每个字节。也就是说无论c多大只有后八位二进制是有效的。

不能任意赋值

注意memset函数是按照字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。初始化其他值可能并不是预期的结果,请看下面这个例子

    int a[] = { 1,2,3,4,5 };
	memset(a, 1, 5*sizeof(int));
 
	for (int i = 0; i < 5; i++)
		printf("%d ", a[i]);
    //16843009 16843009 16843009 16843009 16843009
    printf("\n");

我想把数组元素全部设置为1,但实际上得到的却是非预期值
原因:
数组a是整型的,整型大小为4Byte,而memset函数是按照字节为单位进行赋值,取后8位,将1(00000001)赋给每一个字节。那么对于a[0]来说,其值为(00000001 00000001 00000001 00000001),即十进制的16843009。

-1或者0则没问题

 int a[] = { 1,2,3,4,5 };
	memset(a, 0, 5*sizeof(int));//0 0 0 0 0 
    memset(a, -1, 5*sizeof(int));//-1 -1 -1 -1 -1 
	for (int i = 0; i < 5; i++)
		printf("%d ", a[i]);

    return 0;

字符数组也没问题,因为memset是按1byte来修改的

    char a[5];
	memset(a, 'd', 5); //d d d d d

	for (int i = 0; i < 5; i++)
		printf("%c ", a[i]);

    return 0;

https://blog.csdn.net/weixin_44162361/article/details/115790452

参考资料

https://blog.csdn.net/m0_68814541/article/details/127334335
https://blog.csdn.net/weixin_56810796/article/details/128308824

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/551979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ 期末冲刺3h

C 1. 基础程序 #include "iostream" // C头文件 #include "stdio.h" // C 头文件 //using namespace std; // 命名空间// main() 是程序开始执行的地方int main() {std::cout << "Hello, World!" << "\n";return 0; …

Jenkins持续集成之windows下安装jenkins

官方地址&#xff1a; https://jenkins.io/download/ 安装jenkins 下载windows和linux通用的war包 启动 Jenkins 将 jenkins.war 放到 tomcat安装目录/webapps 下 访问 http://127.0.0.1:8080/jenkins 我这里因为之前已经走过初始化步骤了&#xff0c;所以直接进去了主界面…

Datacom-HCIE 题库 03(10月26日更新)--含解析

单选题 1.[试题编号&#xff1a;189810] &#xff08;单选题&#xff09;SSH算法协商阶段中&#xff0c;双方交换自身所支持的算法列表。SSH服务器的对称加密算法列表依次为:aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc。SSH客户端的对称加密算法列表依次为&#xff1a;aes1…

2023年NOC大赛创客智慧编程赛项图形化复赛模拟题二,包含答案解析

2023年NOC大赛创客智慧编程赛项图形化复赛模拟题二,包含答案解析 第一题: 在源程序“小蝙蝠”文件中,实现小蝙蝠遇到不同的角色会说不同的话,以及切换不同的造型要求: 1:游戏开始时,小蝙蝠角色是造型 a,并能够用键盘控制上、下、左、右移动; 2:移动小蝙蝠,距离角色雪…

利用列表推导式遍历子目录PDF文件

一、问题的提出 之前&#xff0c;我们探索了如何用Python来遍历子目录文件&#xff0c;详情可以见下面的文章&#xff1a; PythonFan&#xff1a;Python遍历子目录文件的多种方法5 赞同 0 评论文章正在上传…重新上传取消https://zhuanlan.zhihu.com/p/609327324 以上方面有…

t检验.医学统计实例详解

t检验是医学统计学中常用的一种假设检验方法&#xff0c;用于比较两个样本均值是否有显著差异。它可以帮助医学研究者确定一个治疗方法或药物是否显著地改善了患者的症状或生理指标。 在医学研究中&#xff0c;t检验常被用来&#xff1a; 比较两个独立样本的均值&#xff1a;…

这个 归并排序详解过程 我能吹一辈子!!!

文章目录 归并排序概念归并排序算法思路归并排序递归实现归并排序非递归实现 归并排序概念 1945年&#xff0c;约翰冯诺依曼&#xff08;John von Neumann&#xff09;发明了归并排序&#xff0c;这是典型的分治算法的应用。 归并排序&#xff08;Merge sort&#xff09;是建立…

【2023秋招】华为od22-12-14三道题(思路+代码)

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&…

Godot引擎 4.0 文档 - 循序渐进教程 - 监听玩家输入

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a; Listening to player input — Godot Engine (stable) documentation in English 监听玩家输入 在上一课创建您的第一个脚本的基础上&#xff0c;让我们看看任何游戏…

Linux基本指令实现4及热键指令详解

目录 Linux热键补充&#xff1a; 1.bc指令&#xff1a; Tab键的智能补充&#xff1a; ctrlc键&#xff1a; uname指令&#xff1a; lscpu指令&#xff1a; lsmem指令&#xff1a; df -h指令&#xff1a; 关机指令&#xff1a; 扩展指令&#xff1a; Linux热键补充&#…

【MySQL通关之旅】从山脚到山顶(傲视群雄版)

查 基本查询 select 查询指定 name,age 字段并返回 select name,age from 表名 查询所有字段并返回 select * from 表名 查询指定 name,age 字段并起别名(姓名,性别) 返回 select name as ‘姓名’,age as ‘性别’ from 表名 去除某字段重复记录 select distinct 字段名 from…

RSA数学基础 连分数

前言 最近在学rsa,补一下连分数 定义 形如 a 0 1 a 1 1 a 2 1 a 3 1 … a_{0}\frac{1}{a_{1}\frac{1}{a_{2}\frac{1}{a_{3}\frac{1}{\ldots}}}} a0​a1​a2​a3​…1​1​1​1​ 的分数 连分数分为有限连分数无限连分数 如上是一个无限连分数 任何一个有理数都可以表示…

【youcans 的图像处理学习课】21. Haar 小波变换

专栏地址&#xff1a;『youcans 的图像处理学习课』 文章目录&#xff1a;『youcans 的图像处理学习课 - 总目录』 【youcans 的图像处理学习课】21. Haar 小波变换 1. 小波变换1.1 小波变换基本概念例程 17_1&#xff1a;常用小波族的图像 1.2 连续小波变换1.3 离散小波变换&a…

【C生万物】 字符串内存函数篇 (下)

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; &#x1f449; 专栏&#xff1a;《C生万物 | 先来学C》&#x1f448; 前言&#xff1a; 承接上篇&#xff0c;在认识了常用的字符串和内存函数后&#xff0c;带大家实现几个函…

idea把项目上传到码云

1. 为项目创建仓库 2. 选中中项目右击git, 先add, 在commit Directory 3. 设置远程码云项目地址 4. push项目, ok。 注意&#xff1a; 如果你在最后push出现以下提示&#xff0c;则说明提交失败 Push to origin/master was rejected(译文&#xff1a;推送到原点/master被拒绝…

联合阿里在职测开工程师耗时一个星期写的 【接口测试+自动化接口接口测试详解]

前言&#xff1a; 兄弟们如果本文让你感觉能学到东西就麻烦各位动动发财的手来个一键三连&#xff0c;听说点赞&#xff0c;收藏&#xff0c;评论&#xff0c;关注的兄弟已经跳槽涨薪发财了哦。 【文章末尾给大家留下了大量的福利】 1&#xff1a;json模块的使用  字典是一种…

华为OD机试真题 Java 实现【最大花费金额】【2023Q1】

一、题目描述 双十一众多商品进行打折销售&#xff0c;小明想购买自己心仪的一些物品&#xff0c;但由于受购买资金限制&#xff0c;所以他决定从众多心仪商品中购买三件&#xff0c;而且想尽可能的花完资金。 现在请你设计一个程序帮助小明计算尽可能花费的最大资金数额。 …

MMDetection 3D入门

MMDetection 3D入门 文章目录 MMDetection 3D入门介绍架构模块核心模块与相关组件公共基础模块 依赖安装最佳实践验证安装 测试数据create_data.py修改数据目录 train.py整体流程命令行参数配置文件中为什么传入参数是 dictRunner函数中参数含义结合图示来理清其中数据的流向与…

深度学习图像识别模型:递归神经网络

深度学习是一种人工智能技术&#xff0c;它用于解决各种问题&#xff0c;包括自然语言处理、计算机视觉等。递归神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是深度学习中的一种神经网络模型&#xff0c;主要用于处理序列数据&#xff0c;例如文本…

电子电气架构——IP地址获取方式汇总

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 我们并不必要为了和谐,而时刻保持通情达理;我们需要具备的是,偶尔有肚量欣然承认在某些方面我们可能会有些不可理喻。该有主见的时候能掷地有声地镇得住场…