一、前言

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 踩坑相关推荐

  1. 使用memset踩过的坑

    使用memset 踩过的坑 库函数 memset() ​ memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的:包含在<[string.h]>头文件中,可以用它对一片内存空间逐 ...

  2. i.MX6ULL裸机篇(二)NXP官方SDK移植之踩坑 网口驱动

    MX6ULL官方SDK移植之踩坑 网口驱动 一.引言 NXP MX6ULL 网口移植其实主要修改底层驱动程序,LWIP协议通用,一般不用修改,这里主要和大家分享在Linux环境下移植修改网口驱动程序. ...

  3. 【golang程序包推荐分享】分享亿点点golang json操作及myJsonMarshal程序包开发的踩坑经历 :)

    目录[阅读时间:约5分钟] 一.概述 1.Json的作用 2.Go官方 encoding/json 包 3. golang json的主要操作 二.Json Marshal:将数据编码成json字符串 ...

  4. java调用clang编译的so_写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实

    好奇害死羊 很多小伙伴们做Java开发,天天写Java代码,肯定离不开Java基础环境:JDK,毕竟我们写好的Java代码也是跑在JVM虚拟机上. 一般来说,我们学Java之前,第一步就是安装JDK环 ...

  5. python导入类有红线_python踩坑系列之导入包时下划红线及报错“No module named”问题...

    python踩坑系列之导入包时下划红线及报错"No module named"问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下 ...

  6. mysql运维工资_MySQL运维踩坑

    image ZERO 背景 本文主要是介绍在MySQL使用运维过程中所遇到的一些坑爹的地方,予自己以做记录! 前言 因操作系统重装之后,安装了mysql5.7,而由此带来了一系列的问题,现将解决这些m ...

  7. 微信跳一跳高分辅助踩坑

    旧博文,搬到 csdn 原文:http://rebootcat.com/2018/01/08/wechat_jump_hack/ 最近挺火的微信跳一跳 最近新版微信的『跳一跳』小程序着实火了一把,也把 ...

  8. 【踩坑记录】记一次MySQL主从复制延迟的坑

    最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...

  9. 分布式深度学习最佳入门(踩坑)指南

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨Lyon@知乎(已授权) 来源丨https://zhuanla ...

最新文章

  1. 数字签名、数字证书、对称加密算法、非对称加密算法、单向加密(散列算法)
  2. linux的passwd命令的作用,Linux passwd 命令的使用
  3. Java黑皮书课后题第8章:*8.3(按考分对学生排序)重写程序清单8-2,按照正确答案个数的升序显示学生
  4. kotlin写的音视频app(已开源)
  5. Windows下保存git账号密码实现免输入
  6. QGIS安装以及使用教程
  7. Zynga任命Noel Watson为董事会成员
  8. 2021年疫情再度爆发,面对停课教培机构该如何应对?
  9. 左手指令_屈老师大班科学教案:猜左手猜右手
  10. 快速云:云计算供应商在合同谈判时可能拒绝的三个事项以及要求
  11. 模具毕业设计题目推荐 / 毕业设计(论文)说明书 CAD图纸 三维模型 开题报告 任务书 实习报告 答辩 ……
  12. PTA---航空公司VIP客户查询 (25分)---Stl-Map容器简单使用
  13. Android无法通过浏览器观看HLS直播的问题
  14. windows server 批量取消域用户属性“密码永不过期”
  15. 80行代码自己动手写一个表格拆分与合并小工具(文末附工具下载)
  16. tab weui 页面切换_weui 多网页切换效果分析
  17. 分享两个超实用的Android开源UI框架——QMUI和XUI
  18. Phpstudy 错误总结
  19. 啊哈C!思考快你一步——用编程轻松提升逻辑力
  20. 数据提取之Xpath

热门文章

  1. akka应用_处理Akka应用程序中的每个事件
  2. 有关Drools业务规则引擎的完整教程
  3. atomiclong_想要更快地使用AtomicLong? 等待它。
  4. 谁去过顽皮,谁去过尼斯? 圣诞老人为您提供Java 11建议!
  5. java低延迟_像Java这样的C ++具有低延迟
  6. 如何将JAR添加到Jetbrains MPS项目
  7. json套json_JSON –拯救杰克逊
  8. Netflix Archaius用于物业管理–基础知识
  9. JUnit:使用Java 8和AssertJ 3.0.0测试异常
  10. 针对新手的Java EE7和Maven项目-第4部分-定义Ear模块