C memset 踩坑
一、前言
memset 作为对内存初始化的函数,还是有不少坑和误区的,今天就来对这个函数作一个总结。
二、函数作用
最简单的调用就是将一个数组清零,代码如下:
const int maxn = 1024;
int a[maxn];
memset(a, 0, sizeof(a)); // a[0]=a[1]=a[...]=0;
这里 sizeof(a) = maxn * 4 = 4096;
表示的是将 数组首地址 a 开始往后的 4096 个字节,都设置为 0;
三、效率对比
直接调用 memset 接口清零 和 调用循环进行清零,进行一个测试后如下:
对长度为 10000000 的数组,执行100次调用;
模式 | memset | for |
debug |
375ms |
2156ms |
release |
343ms |
329ms |
因为 release 版本会做各种优化,编译器发现重复执行无效逻辑就会跳过,所以不太好造数据测试,研究时间效率的时候还是参考 debug 版本(当然,软件发布的时候肯定用的是 release 版本)。
memset 无论从时间效率,还是代码整洁来看都是由于 for 循环的,当然也带来了一些容易引起误解的地方。
四、误区总结
1、按字节设置
memset 实现原理是根据字节来设置的,比如对于字节数组
char a[100]
,将所有字节都设置为5,就可以调用:
memset(a, 5, sizeof(a));
但是,对于
int b[100]
,也采用这种方法,就会导致错误:
memset(b, 5, sizeof(b));
得到 b 数组中元素的值为 84215045;
为什么呢?
我们把这个数组转换成二进制,得到:
( 00000101 00000101 00000101 00000101 ) 2 (00000101 \ 0000 0101 \ 0000 0101 \ 0000 0101)_2 (00000101 00000101 00000101 00000101)2因为 i n t int int 占据了 4 4 4 个字节,把每个字节都设置成了5,所以最后转成十进制就变成了 84215045;
同理,当类型是 short(二字节整数),或者 long long(八字节整数)都会有类似问题,总结表格如下:
memset值 | char | short | int | long long |
0 |
0 |
0 |
0 |
0 |
-1 |
-1 |
-1 |
-1 |
-1 |
5 |
5 |
1285 |
84215045 |
361700864190383365 |
表格中,只有0 和 -1是正常的,因为 0 的二进制表示中,所有位都为0;-1 的二进制表示中,所有位都为 1;
特别的,当需要设置的数,对应类型的每个字节都是同一个数的时候,也可以采用 memset,比如:int 类型的 252645135(十六进制表示为:0x0f0f0f0f);
2、设置的值只有最低字节有效
memset(a, 0x05ffffff, sizeof(a));
memset(a, 0xffffff05, sizeof(a));
memset(a, 0xffffff08, sizeof(a));
memset(a, 0x12345678, sizeof(a));
设置值的时候,只会采用最低的字节作为赋值用,通俗的讲,就是以上四句话调用,等价于:
memset(a, 0xff, sizeof(a));
memset(a, 0x05, sizeof(a));
memset(a, 0x08, sizeof(a));
memset(a, 0x78, sizeof(a));
3、堆内存不可直接 sizeof 取首地址
在堆上申请了一个数组空间,并且想要给它初始化,调用如下:
const int maxn = 1024;
int *p = new [maxn];
memset(p, 0, sizeof(p));
这里进入了另一个误区,因为 p p p 在这里虽然是数组首地址,但是它扮演的角色更多的,其实是个指针,所以在进行 sizeof 运算符操作的时候,取得的值并不是 4096,而是指针的大小;
32位机子上,指针大小为4,;64位机子上,指针大小为 8;
正确做法是:
const int maxn = 1024;
int *p = new [maxn];
memset(p, 0, maxn * sizeof(int));
4、传参数组不可直接 sizeof 取首地址
对传参为数组的数据进行 memset,调用如下:
void fun(int a[maxn]) {memset(a, 0, sizeof(a));
}
这里调用同样是错误的,因为当数组作为传参的时候,这里的 a 已经退化为指针,所以同样不能用 sizeof 数组首地址来取大小;
正确做法是:
void fun(int a[maxn]) {memset(a, 0, maxn * sizeof(int));
}
当然,当传参是结构体指针的时候也是如此;
- EOF -
来源:
https://blog.csdn.net/WhereIsHeroFrom/article/details/111660632
C memset 踩坑相关推荐
- 使用memset踩过的坑
使用memset 踩过的坑 库函数 memset() memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的:包含在<[string.h]>头文件中,可以用它对一片内存空间逐 ...
- i.MX6ULL裸机篇(二)NXP官方SDK移植之踩坑 网口驱动
MX6ULL官方SDK移植之踩坑 网口驱动 一.引言 NXP MX6ULL 网口移植其实主要修改底层驱动程序,LWIP协议通用,一般不用修改,这里主要和大家分享在Linux环境下移植修改网口驱动程序. ...
- 【golang程序包推荐分享】分享亿点点golang json操作及myJsonMarshal程序包开发的踩坑经历 :)
目录[阅读时间:约5分钟] 一.概述 1.Json的作用 2.Go官方 encoding/json 包 3. golang json的主要操作 二.Json Marshal:将数据编码成json字符串 ...
- java调用clang编译的so_写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实
好奇害死羊 很多小伙伴们做Java开发,天天写Java代码,肯定离不开Java基础环境:JDK,毕竟我们写好的Java代码也是跑在JVM虚拟机上. 一般来说,我们学Java之前,第一步就是安装JDK环 ...
- python导入类有红线_python踩坑系列之导入包时下划红线及报错“No module named”问题...
python踩坑系列之导入包时下划红线及报错"No module named"问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下 ...
- mysql运维工资_MySQL运维踩坑
image ZERO 背景 本文主要是介绍在MySQL使用运维过程中所遇到的一些坑爹的地方,予自己以做记录! 前言 因操作系统重装之后,安装了mysql5.7,而由此带来了一系列的问题,现将解决这些m ...
- 微信跳一跳高分辅助踩坑
旧博文,搬到 csdn 原文:http://rebootcat.com/2018/01/08/wechat_jump_hack/ 最近挺火的微信跳一跳 最近新版微信的『跳一跳』小程序着实火了一把,也把 ...
- 【踩坑记录】记一次MySQL主从复制延迟的坑
最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...
- 分布式深度学习最佳入门(踩坑)指南
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨Lyon@知乎(已授权) 来源丨https://zhuanla ...
最新文章
- 数字签名、数字证书、对称加密算法、非对称加密算法、单向加密(散列算法)
- linux的passwd命令的作用,Linux passwd 命令的使用
- Java黑皮书课后题第8章:*8.3(按考分对学生排序)重写程序清单8-2,按照正确答案个数的升序显示学生
- kotlin写的音视频app(已开源)
- Windows下保存git账号密码实现免输入
- QGIS安装以及使用教程
- Zynga任命Noel Watson为董事会成员
- 2021年疫情再度爆发,面对停课教培机构该如何应对?
- 左手指令_屈老师大班科学教案:猜左手猜右手
- 快速云:云计算供应商在合同谈判时可能拒绝的三个事项以及要求
- 模具毕业设计题目推荐 / 毕业设计(论文)说明书 CAD图纸 三维模型 开题报告 任务书 实习报告 答辩 ……
- PTA---航空公司VIP客户查询 (25分)---Stl-Map容器简单使用
- Android无法通过浏览器观看HLS直播的问题
- windows server 批量取消域用户属性“密码永不过期”
- 80行代码自己动手写一个表格拆分与合并小工具(文末附工具下载)
- tab weui 页面切换_weui 多网页切换效果分析
- 分享两个超实用的Android开源UI框架——QMUI和XUI
- Phpstudy 错误总结
- 啊哈C!思考快你一步——用编程轻松提升逻辑力
- 数据提取之Xpath
热门文章
- akka应用_处理Akka应用程序中的每个事件
- 有关Drools业务规则引擎的完整教程
- atomiclong_想要更快地使用AtomicLong? 等待它。
- 谁去过顽皮,谁去过尼斯? 圣诞老人为您提供Java 11建议!
- java低延迟_像Java这样的C ++具有低延迟
- 如何将JAR添加到Jetbrains MPS项目
- json套json_JSON –拯救杰克逊
- Netflix Archaius用于物业管理–基础知识
- JUnit:使用Java 8和AssertJ 3.0.0测试异常
- 针对新手的Java EE7和Maven项目-第4部分-定义Ear模块